RTI Connext DDS代码生成器

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

0 简介

RTI®代码生成器Code Generator,创建用RTI Connext®DDS定义define和注册register用户数据类型所需的代码。

在以下情况下使用代码生成器是可选的

  • 您正在使用动态类型请参阅RTI Connext DDS核心库用户手册[RTI ConnextDDS Core Libraries Users Manual]中的“管理内置类型的内存”第3.2.7节。

  • 您正在使用一种内置类型请参阅RTI Connext DDS核心库用户手册[RTI ConnextDDS Core Libraries Users Manual]中的内置数据类型第3.2节。

要使用代码生成器Code Generator您需要在IDL或XML文件中提供数据类型的描述。可以在同一类型定义文件中定义多个数据类型。有关这些文件的详细信息请参阅RTIConnext DDS核心库用户手册[RTI Connext DDS CoreLibraries Users Manual]第3.3节和第3.4节。

1 常用路径

1.1 <NDDSHOME>

这是指RTI®Connext®DDS的安装目录。默认安装路径为

  • macOSsystems:

/Applications/rti_connext_dds-6.1.1

  • Linuxsystems, non-root user:

/home/<youruser name>/rti_connext_dds-6.1.1

  • Linux systems,root user:

/opt/rti_connext_dds-6.1.1

  • Windowssystems, user without Administrator privileges:

<yourhome directory>\rti_connext_dds-6.1.1

  • Windowssystems, user with Administrator privileges:

C:\ProgramFiles\rti_connext_dds-6.1.1

您还可以看到$NDDSHOME或%NDDSHOME%它是指设置到安装路径的环境变量。

无论您在路径中看到<NDDSHOME>请将其替换为安装路径。

Windows用户注意使用命令提示符输入包含路径C:\Program Files或任何有空格的目录名的命令时请将路径括在引号中。例如

“C:\ProgramFiles\rti_connext_dds6.1.1\bin\rtiddsgen”

或者如果已定义NDDSHOME环境变量

“%NDDSHOME%\bin\rtiddsgen”

1.2 <pathto examples>

默认情况下当您第一次运行RTI Launcher或<NDDSHOME>/bin中的任何脚本时会将示例复制到主目录中。本文档将复制示例的位置称为

<path to examples >。

无论您在哪里看到<path toexamples>请将其替换为适当的路径。

示例的默认路径

  • macOS系统/Users/<用户名>/rti_workspace/6.1.1/examples

  • Linux系统/home/<用户名>/rti_workspace/6.1.1/example

  • Windows系统<您的Windows文档文件夹>\rti_workspace\6.1.1\examples其中“您的Windows文件文件夹”取决于您的Windows版本。例如在Windows 10上文件夹为C:\Users\<用户名>\Documents。

注意您可以为rti_workspace指定不同的位置。还可以指定不希望将示例复制到工作空间。有关详细信息请参阅《RTI Connext DDS安装指南》中的“控制RTI工作区位置和复制示例”。

2 rtiddsgen的命令行参数

在Windows系统上在运行rtiddsgen之前请在运行rtiddsgen所使用的同一命令提示符中运行适用于您的体系结构的“vcvars”批处理文件。例如

vcvarsall.batx86。

“vcvars”批处理文件的位置因您的Visual Studio版本而异。有关安装的确切位置和参数请参阅MicrosoftVisual Studio文档。或者从Visual Studio Tools文件夹下的Visual Studio命令提示符运行rtiddsgen。或者使用命令行参数ppDisable。请参见第6页表3.1rtiddsgen选项中的-ppDisable。

如果要为Connext DDS生成代码则选项如下

rtiddsgen [-help]

[-allocateWithMalloc]

[-alwaysUseStdVector]

[-autoGenFiles <architecture>]

[-constructor]

[-create <typefiles| examplefiles|makefiles>]

[-convertToIdl | -convertToXML | -convertToXsd]

[-D <name>[=<value>]]

[-d <outdir>]

[-disableXSDValidation]

[-dllExportMacroSuffix <suffix>]

[-dotnet <modern|legacy>]

[-enableEscapeChar]

[-example <architecture>]

[-exampleTemplate]

[-I <directory>]

[[-inputIdl] <IDLInputFile.idl> | [-inputXml] <XMLInputFile.xml>

|[-inputXsd <IDLInputFile.idl>]]

[-language <Ada|C|C++|C++11|C++/CLI|C#|Java>]

[-namespace]

[-obfuscate]

[-optimization <level>]

[-package <packagePrefix>]

[-platform <architecture>]

[-ppDisable]

[-ppPath <path to preprocessor>]

[-ppOption <option>]

[-qualifiedEnumerator]

[-reader]

[-replace]

[-sequenceSize <unbounded sequences size>]

[-sharedLib]

[-showTemplates]

[-strict]

[-stringSize <unbounded strings size>]

[-typeSequenceSuffix <suffix>]

[-U <name>]

[-unboundedSupport]

[-update <typefiles| examplefiles|makefiles>]

[-use52Keyhash]

[-use526Keyhash]

[-useStdString]

[-V <name< [=<value>]]

[-verbosity [1-3]]

[-version]

[-virtualDestructor]

[-writer]

如果您正在为RTI Connext DDSMicro生成代码则选项如下

rtiddsgen [-help]

[-create <typefiles| examplefiles|makefiles>]

[-convertToIdl | -convertToXML]

[-D <name>[=<value>]]

[-d <outdir>]

[-enableEscapeChar]

[-example]

[-exampleTemplate]

[-I <directory>]

[[-inputIdl] <IDLInputFile.idl> | [-inputXml] <XMLInputFile.xml>]

[-language <C|C++>]

[-micro]

[-namespace]

[-ppDisable]

[-ppPath <path to preprocessor>]

[-ppOption <option>]

[-reader]

[-replace]

[-showTemplates]

[-sequenceSize <unbounded sequences size>]

[-strict]

[-stringSize <unbounded strings size>]

[-U <name>]

[-update <typefiles| examplefiles|makefiles>]

[-V <name< [=<value>]]

[-verbosity [1-3]]

[-version]

[-writer]

注意在使用代码生成器创建的makefile来编译应用程序之前请确保${NDDSHOME}环境变量的设置如中的设置环境变量artisetenv所述RTI Connext DDS入门指南中(RTI Connext DDS GettingStarted Guide.)发布/订阅简介的“动手1”。

表3.1 rtiddsgen选项

选项

描述

-allocateWithMalloc

在C++中使用DDS_Heap_malloc分配可选成员时使用此标志可获得向后兼容性。

-alwaysUseStdVector

仅适用于指定了-语言C++11的情况。

生成将所有序列映射到std:vector的代码甚至将映射到rti:core:bounded_sequence的有界序列。

或者@use_vector注释可以应用于每个序列成员。

-autoGenFiles <architecture>

更新自动生成的文件即typefile和makefile/项目文件。

要查看每种语言的<体系结构>有效选项请使用-help选项运行rtiddsgen或使用字符串

“通用”-autoGenFiles通用为所有支持的平台生成兼容的发布者/订户代码。universalarchitecture不会生成makefile/项目文件。

这是以下项的快捷方式

-更新typefiles-更新makefiles-平台<体系结构>

-constructor

仅当同时指定了-语言C++时适用。

生成类型默认构造函数、复制构造函数、复制赋值运算符和析构函数。使用此选项还将禁用以下TypeSupport方法的生成create_data_ex、delete_

data_ex、initialize_data_e x、finalize_data。

-create <typefiles| examplefiles|makefiles>

创建指定的文件typefile、examplefile或makefile如果它们不存在。例如

rtiddsgen-语言C++11-创建类型文件test.idl如果文件已经存在则不会修改文件并打印警告。

可以有多个创建选项。

如果为同一文件类型同时指定-create和-update则只应用-update。

如果使用-create makefile则需要-platform<arch>选项。例如

rtiddsgen-语言c-创建makefile-平台x64Darwin17clang9.0 test.idl

-convertToIdl

将输入类型描述文件转换为IDL格式。此选项将创建一个与输入文件同名且扩展名为.idl的新文件。

-convertToXML

将输入类型描述文件转换为XML格式。此选项创建一个与输入文件同名且扩展名为.xml的新文件。

-convertToXsd

将输入类型描述文件转换为XSD格式。此选项将创建一个与输入文件同名且扩展名为.xsd的新文件。

-D <name>[=<value>]

定义预处理器宏。

在Windows系统上将参数括在引号中

-D“<name>[=<value>]”

-d <outdir>

在指定目录中生成输出。默认情况下代码生成器将在找到输入类型定义文件的目录中生成文件。

-disableXSDValidation

导致代码生成器不检查输入XSD文件的格式是否正确。

通常不建议使用此选项因为代码生成器可能会收到无效输入。

-dllExportMacroSuffix <suffix>

定义在生成Windows DLL时用于导出符号的宏的后缀。默认宏为NDDS_USER_DLL_EXPORT。指定此选项时宏的名称为NDDS_USER_DLL_

EXPORT_<后缀>。

3 生成示例代码

大多数Connext DDS入门指南如RTI Connext DDS《入门指南》或RTI Connxt DDS核心库《嵌入式系统入门指南附录》都要求您创建一个简单的“HelloWorld”应用程序来入门。例如在macOS上

$rtiddsgen -language c++11 -example x64Darwin17clang9.0 hello_world.idl

注意在使用代码生成器Code Generator创建的makefile来编译应用程序之前请确保按照RTI Connext DDS入门指南中发布/订阅简介的“Hands On 1”中的设置环境变量artisetenv中所述设置了${NDDSHOME}环境变量。

熟悉简单的HelloWorld示例后可以通过指定“高级”模板选项来创建更高级的示例。高级模板已包含在代码生成器中请参见-exampleTemplate和-showTemplates。例如在macOS上

rtiddsgen -language C+11 -example x64Darwin17clang9.0 -exampleTemplate advanced hello_ world.idl

代码生成器生成的简单示例和高级示例之间有一些主要区别。

注意Android不支持高级生成的示例™ 或INTEGRITY®平台。

3.1 is_default_qos(true vs. false)

ConnextDDS从当前工作目录中名为USER_QOS_PROFILES.xml的文件加载QoS配置文件。Connext DDS也可以在其他位置查找此文件请参阅RTI Connext DDS核心库用户手册中的“如何加载XML指定的QoS设置”。

简单示例在USER_QOS_PROFILES.xml文件中设置is_default_qos=true。它创建DDS实体而不指定配置文件因此使用USER_QOS_PROFILES.xml中的默认值。

高级示例还从USER_QoS_PROFILES.xml文件加载QoS。但是高级示例将is_default_qos设置为false因此XML没有提供默认值。该示例明确指定了在创建DDS实体时要从XML文件中使用的QoS配置文件。

设置is_default_qos=true是快速入门的一种方便方法但在生产应用程序中您应该明确指定要使用的qos配置文件而不是依赖默认值。请参阅RTI Connext DDS入门指南中的基本QoS一章。

3.2 侦听器Listeners与等待集WaitSets

简单和高级示例都使用WaitSets来阻塞线程直到数据可用。这是获取数据的最安全的方法因为它不会影响任何中间件线程它会阻塞应用程序的主线程直到数据可用。

此外该高级示例在DataReader和DataWriter上安装侦听器并提供回调您可以实现这些回调以实现所需的行为。这些侦听器回调是针对各种事件触发的例如发现匹配的DataWriter或DataReader。侦听器回调是从中间件线程回调的您不应该阻止它。使用监听器进行非数据回调有好处因为您不会错过事件。但是如果在侦听器中阻止或执行缓慢的处理则可能会导致不希望的行为例如数据丢失。请参阅RTI Connext DDS核心库用户手册中的侦听器一章。

4 产生文件

下表显示了代码生成器为名为Hello.IDL的示例IDL文件创建的文件。

  • 表5.1 C、传统C++、C++/CLI、为示例“Hello.idl”创建的旧C#文件

  • 表5.2为示例“Hello.idl”创建的现代C++文件

  • 表5.3为示例“Hello.idl”创建的C#文件

  • 表5.4为示例“Hello.idl”创建的Java文件

  • 表5.5为示例“Hello.idl”创建的Ada文件

表5.1 C、传统C++、C++/CLI、为示例创建的旧C#文件“Hello.idl”

产生文件

描述

用户数据类型需要以下文件。源文件应编译并与应用程序链接。需要头文件才能在源中使用数据类型。

除非您打算自定义生成的支持您类型的代码否则不应修改这些文件。

Hello.[c, cxx, cpp]

HelloSupport.[c, cxx, cpp]

HelloPlugin.[c, cxx, cpp]

为数据类型生成的代码。这些文件包含数据类型的实现。

Hello.h

HelloSupport.h

HelloPlugin.h

包含数据类型实现中使用的声明的头文件。

使用-example<architecture>命令行选项时会生成以下可选文件。您可以修改并使用这些文件作为创建发布或订阅用户数据类型的简单应用程序的方法。

application.h (traditional C++ only)

Hello_publisher.cxxand Hello_subscriber.cxxapplications的帮助程序代码

Hello_publisher.[c, cxx, cpp, cs]

发布用户数据类型的应用程序的示例代码。此示例显示了创建发送数据所需的所有DDS对象的基本步骤。

您需要修改代码以设置和更改数据结构中发送的值。否则只需编译并运行。

Hello_subscriber.[c, cxx, cpp,cs]

订阅用户数据类型的应用程序的示例代码。此示例显示了创建接收数据所需的所有DDS对象的基本步骤。

不需要修改此文件。它已准备好供您编译和运行。

Hello-<architecture>.sln

Hello_publisher-<architecture>.v[c, cs, cx]proj

Hello_subscriber-<architecture>.v[c, cs, cx]-proj

Microsoft Visual Studio解决方案和项目文件仅为基于Visual Studio的体系结构生成。示例<architecture>isarmv8Linux4gcc7.3.0。要编译生成的源代码请打开工作区文件并构建两个项目。

makefile_Hello_<architecture>

非基于Visual Studio的架构的Makefile。一个<体系结构>的例子是rmv8Linux4gcc7.3.0。

USER_QOS_PROFILES.xml

生成的示例中DDS实体的服务质量QoS配置从该文件加载。

表5.2为示例“Hello.idl”创建的现代C++文件

产生文件

描述

用户数据类型需要以下文件。源文件应编译并与应用程序链接。需要头文件才能在源中使用数据类型。

除非您打算自定义生成的支持您类型的代码否则不应修改这些文件。

Hello.cxx

HelloPlugin.cxx

为数据类型生成的代码。这些文件包含数据类型的实现。

Hello.hpp

HelloPlugin.hpp

包含数据类型实现中使用的声明的头文件

使用-example<architecture>命令行选项时会生成以下可选文件。您可以修改并使用这些文件作为创建发布或订阅用户数据类型的简单应用程序的方法。

application.hpp

Hello_publisher.cxxand Hello_subscriber.cxxapplications的帮助程序代码

Hello_publisher.cxx

发布用户数据类型的应用程序的示例代码。此示例显示了创建发送数据所需的所有DDS对象的基本步骤。

您需要修改代码以设置和更改数据结构中发送的值。否则只需编译并运行。

Hello_subscriber.cxx

订阅用户数据类型的应用程序的示例代码。此示例显示了创建接收数据所需的所有DDS对象的基本步骤。

不需要修改此文件。它已准备好供您编译和运行。

Hello-<architecture>.sln

Hello_publisher-<architecture>.vcxproj

Hello_subscriber-<architecture>.vcxproj

Microsoft Visual Studio解决方案和项目文件仅为基于Visual Studio的体系结构生成。示例<architecture>isarmv8Linux4gcc7.3.0。要编译生成的源代码请打开工作区文件并构建两个项目。

makefile_Hello_<architecture>

非基于Visual Studio的架构的Makefile。一个<体系结构>的例子是rmv8Linux4gcc7.3.0。

USER_QOS_PROFILES.xml

生成的示例中DDS实体的服务质量QoS配置从该文件加载。

表5.3为示例“Hello.idl”创建的C#文件

产生文件

描述

用户数据类型需要以下文件。源文件应与.NET项目一起编译。

您不应修改这些文件。

Hello.cs

HelloPlugin.cs

为数据类型生成的代码。这些文件包含数据类型的实现。

使用-example<platform>命令行选项其中<platform>

是.NET平台标识符如net5或netcoreapp3.1。您可以修改并使用这些文件来创建发布或订阅用户数据类型的简单应用程序。

HelloProgram.cs

运行HelloPublisher.cs和HelloSubscriber.cs应用程序的代码

HelloPublisher.cs

发布用户数据类型的应用程序的示例代码。此示例显示了创建发送数据所需的所有DDS对象的基本步骤。

您需要修改代码以设置和更改数据结构中发送的值。否则只需编译并运行。

HelloSubscriber.cs

订阅用户数据类型的应用程序的示例代码。

此示例显示了创建接收数据所需的所有DDS对象的基本步骤。

不需要修改此文件。它已准备好供您编译和运行。

Hello.csproj

NuGet.Config

用于构建和运行应用程序。NuGet.Config告诉.NET编译器在哪里可以找到Rti.ConnextDds NuGet包。

USER_QOS_PROFILES.xml

生成的示例中DDS实体的服务质量QoS配置从该文件加载。

表5.4为示例“Hello.idl”创建的Java文件

类型

产生文件

描述

由于Java语言要求为每个类创建单独的文件所以Code Generator将为每个IDL构造生成一个源文件并将其转换为Java中的类。

常量

Hello.java

与常量关联的类

枚举

Hello.java

与枚举类型关联的类

结构/活接头

Hello.java

HelloSeq.java

HelloDataReader.java

HelloDataWriter.java

HelloTypeSupport.java

结构/联合类序列类DDS DataReader和DataWriter类支持序列化、反序列化等类

序列数组的类型定义

Hello.java

HelloSeq.java

HelloTypeSupport.java

包装类序列类支持序列化、反序列化等类

使用-example<architecture>命令行选项时会生成以下可选文件。您可以修改并使用这些文件作为创建发布或订阅用户数据类型的简单应用程序的方法。

最后一个结构/联合

HelloPublisher.java HelloSubscriber.java

发布或订阅用户数据类型的应用程序的示例代码。您应该修改发布应用程序中的代码以设置和更改发布数据的值。否则两个文件都应该准备好编译和运行。

makefile_Hello_

<architecture>

非基于Windows的体系结构的Makefile。一个<体系结构>的例子是rmv8Linux4gcc7.3.0。

USER_QOS_PROFILES.xml

生成的示例中DDS实体的服务质量QoS配置从该文件加载。

结构/活接头/

类型定义/枚举

HelloTypeCode.java

与IDL类型关联的类型代码类Hello

USER_QOS_PROFILES.xml

生成的示例中DDS实体的服务质量QoS配置从该文件加载。

表5.5为示例“Hello.idl”创建的Ada文件

产生文件

描述

Hello[.h,.c]

为数据类型生成的代码其中包含数据类型的实现以及包含数据类型实现中使用的声明的头文件。

HelloSupport[.h,.c]

HelloPlugin[.h,.c]

hello_idl_file[.adb, .ads]

hello_idl_file-hello_datawriter.ads

DataReader和DataWriter类以及序列化/反序列化方法。

hello_idl_file-hello_datawriter.ads

hello_idl_file-hello_typesupport[.adb,.ads]

hello_idl_file-hello_metptypesupport[.adb,.ads]

这些文件仅为支持零拷贝传输共享内存的类型生成即在IDL文件中用@transfer_modeSHMEM_REF注释。

hello_idl_file-hello_publisher[.adb.ads]在示例/目录中

发布用户数据类型的应用程序的示例代码。您需要修改代码以设置和更改数据结构中发送的值。否则只需编译并运行。subscriberlistener文件实现了on_data_available回调。

hello_idl_file-hello_subscriber[.adb.ads]在示例/目录中

hello_idl_file-hello_subscriberlistener[.adb.ads]在示例/目录中

hello.gpr

使用类似Ada语法的项目文件。这些文件定义了应用程序的构建相关特性。这些特征包括源列表、这些源的位置、生成的对象文件的位置、主程序的名称以及构建过程中涉及的各种工具的选项。每个文件都是一组不同的文件hello示例用于示例hello_c用于c文件hello用于其余ada文件

hello_c.gpr

hello-samples.gpr (in the samples directory)

使用-example<architecture>命令行选项时会生成以下可选文件。您可以修改并使用此文件来创建发布或订阅用户数据类型的简单应用程序。

USER_QOS_PROFILES.xml

生成的示例中DDS实体的服务质量QoS配置从该文件加载。

5 自定义生成的代码

代码生成器允许您通过更改提供的模板为不同的语言自定义生成的代码。此版本不允许您创建新的输出文件。

可以在现有模板中使用以下命令加载新模板其中<pathToTemplate>是具有自定义模板的文件夹的绝对路径

#parse(“<pathToTemplate>/template.vm”)

如果template.vm文件包含宏则可以在原始模板中使用它。如果template.vm仅包含纯文本而没有宏则该文本将直接包含在原始文件中。

您可以使用代码生成器提供的预定义变量集自定义模板的行为。有关详细信息请参阅RTI_rtiddsgen_template_variables.xlsx中的表。

此文件包含两个不同的工作表语言模板Language-Templates和模板变量Template variables。语言模板工作表显示了所使用的Velocity模板与为每种语言生成的文件之间的对应关系。例如如果我们想在Hello.C文件中添加一个C语言的方法我们需要修改templates/C目录下的模板类型Body.vm。

模板的范围可以是

  • 类型type如果我们为IDL文件中的每种类型生成一个带有该模板的文件。例如在Java中我们为IDL中的每个类型生成一个TypeSupport文件。

  • file如果我们为每个IDL文件生成一个带有该模板的文件。例如在C中我们生成一个包含所有类型插件信息的插件文件。

  • lastTopLevelType如果我们使用IDL文件中最后一个顶级类型的模板生成一个文件。这通常用于发布者/订阅者示例。

  • 模块如果我们为IDL文件中的每个模块生成一个带有该模板的文件。这在Ada中使用其中有包含模块所有类型的文件。

  • topLevelType如果我们为idl文件中的每个类型生成一个具有该模板的文件。这在ADA中使用其中发布者/订阅者文件仅为顶级类型生成

该表还显示了可用于该模板的top_level变量。这些变量在工作表模板变量中进行了说明。例如在Java中变量的主要单位是constructMap它是表示类型的变量的hashMap。在C语言中我们将constructMapList作为主要单元它是constructMap的列表。在模板变量表中我们可以看到每个constructMap中包含哪些变量它适用于的constructKind或类型以及它包含的值具体取决于我们使用的语言。

包含类型的constructMap的一个重要变量是memberFieldMapList。此列表表示类型中包含的成员。每个成员也表示为hashMap其变量也在模板变量表中描述。

除此之外还有一些环境或常规变量与在名为envMap的hashMap中定义的类型无关。

让我们看一个例子如何使用这些变量。假设我们要在C中生成一个方法该方法打印结构的成员如果是数组或序列则打印相应的大小。对于此IDL

module Mymodule{

struct MyStruct{

int32 longMember;

int32 arrayMember [2][100];

sequence<char,2> sequenceMember;

sequence <int32, 5> arrayOfSequenceMember[28];

};

};

我们希望生成以下内容

void MyModule_MyStruct_specialPrint(){

printf(" longMember \n");

printf(" arrayMember is an array [2, 100] \n ");

printf(" sequenceMember is a sequence <2> \n");

printf(" arrayOfSequenceMember is an array [28] is a sequence <5> ");

}

模板中的代码如下所示

## We go through all the list of types

#foreach ($node in $constructMapList)

##We only want the method for structs

#*--*##if ($node.constructKind.equals(“¡ãstruct”¡À))

void ${node. nativeFQName}_specialPrint(){

##We go through all the members and call to the macros that check if they are array or

sequences

#*----*##foreach($member in $node.memberFieldMapList)

print("$member.name #isAnArray($member) #isASeq($member) \n");

#*----*##end

}

#*--*##end

#end

isAnArray宏检查成员是否为数组即具有变量dimensionList在这种情况下打印它

#macro (isAnArray $member)

#if($member.dimensionList) is an array $member.dimensionList #end

#end

isASeq宏检查成员是否为序列即具有变量seqSize在这种情况下打印它

#macro (isASeq $member)

#if($member.seqSize) is a sequence <$member.seqSize> #end

#end

启动代码生成器时可以使用-V<name<[=<value>]命令行选项将新变量添加到模板中。此变量将添加到userVarList hashMap中。您可以在模板中将其称为$userVarList.name或$userVarList.name.equalsvalue。

有关速度模板的详细信息请参见https://velocity.apache.org/engine/1.5/user-guide.html.

6 优化代码生成过程

序列化serialization和反序列化deserialization操作的成本随着类型复杂性typecomplexity和样本大小sample size的增加而增加。它可以成为发送和接收样本所需的延迟的重要因素。

代码生成器Code Generator提供了命令行选项-optimization可用于指示序列化serialize/反序列化deserialize操作的优化级别level of optimization。此命令行选项允许选择三个不同级别中的一个。

6.1 优化级别

  • 0:无优化

  • 1:rtiddsgen为typedef生成额外代码但优化了其使用。如果使用的类型是可以解析为基元、枚举或聚合类型结构struct、联合union或值类型的typedef则生成的代码将调用可以解析typedef的最基本类型的代码。如果不希望修改为typedef生成的代码则可以使用此级别。

这是Java、C#和C++/CLI语言支持的唯一优化级别。

例如

typedef int32 Latitude;

typedef int32 Longitude;

struct Position {

Latitude x;

Longitude y;

};

对于优化0Position类型的样本的序列化将需要调用Latitude和Longitude的序列化方法。例如

LatitudePlugin_serialize(...) {

serialize_long(...)

}

LongitudePlugin_serialize(...) {

serialize_long(...)

}

Position_serialize(...) {

LatitudePlugin_serialize(...)

LongitudePlugin_serialize(...)

}

通过优化1rtiddsgen将纬度Latitude和经度Longitude解析为最原始的类型以实现序列化从而实现更高效的序列化。在这种情况下rtiddsgen将保存两个函数/方法调用。

Position_serialize(...) {

serialize_long(...)

serialize_long(...)

}

  • 2 如果未指定则此优化级别为默认值。您也可以明确指定。此优化级别仅适用于C、C++、C++11、microC、microC++和Ada语言。使用此优化级别rtiddsgen通过使用更积极的技术来优化结构struct和值类型的序列化/反序列化。这些技术包括嵌套类型nested types的内联扩展以及当内存布局CC++结构布局与连线布局XCDR相同时使用单个复制函数调用memcpy对一组连续成员进行序列化serialization/反序列化deserialization。

6.2 如何应用优化

在代码生成器中优化嵌套类型的内联扩展和具有单个副本的连续成员的序列化是相关的。嵌套结构的内联扩展仅在具有结构标准封装的C/C++内存布局与XCDR布局匹配时进行。在这种情况下可以使用单个memcpy对结构的成员进行序列化。如果具有结构的标准封装的C/C++内存布局与XCDR布局匹配则rtiddsgen将首先尝试进行内联扩展然后使用单个副本对连续成员进行串行化serialization。

6.2.1 嵌套类型nested types的内联扩展

内联扩展是一种优化其中代码生成器将一个类型定义替换为另一个嵌套类型被展平的类型定义。这样做是为了在序列化serialization/反序列化deserialization期间删除额外的函数调用。例如

struct Point {

int32 x;

int32 y;

};

struct Dimension {

int32 height;

int32 width;

};

struct Rectangle {

Point leftTop;

Dimension size;

};

对于优化级别2代码生成器将矩形的定义替换为以下等效定义

struct Rectangle {

int32 leftTop_x;

int32 leftTop_y;

int32 size_height;

int32 size_width;

};

此优化仅用于序列化/反序列化。C/C++中生成的类型继续使用点和维度。

6.2.2 使用单个副本序列化连续成员

在前面的矩形示例中代码生成器使用优化级别2通过使用单个复制single copy操作memcpy而不是四个来序列化矩形样本进一步优化了序列化和反序列化。

  • 优化前

Rectangle_serialize(...) {

memcpy(..., 4) // leftTop_x

memcpy(..., 4) // leftTop_y

memcpy(..., 4) // size_height

memcpy(..., 4) // size_width

}

  • 优化后

Rectangle_serialize(...) {

memcpy(..., 16) // leftTop_x

}

此优化仅在C/C++结构的内存布局与串行化布局等效时适用后者使用XCDR版本1或版本2格式。

6.2.3 内联扩展规则

要实现内联结构“MyStruct”必须满足以下两个要求

  • 它必须具有C/C++友好的XCDR布局。

  • “MyStruct”的任何成员都不应标记为@min、@max或@range注释。

当满足以下所有条件时结构/值类型“MyStruct”具有C/C++友好的XCDR布局

  • 当数据表示为XCDR版本1时MyStruct标记为@final或@appendable。可变结构不可内联。

  • MyStruct没有基类型。

  • MyStruct仅包含基本成员或仅由基本成员组成的复杂成员。基元成员是具有以下任意类型的成员int8uint8、int16、int32、int64、uint16、uint32、uint64、浮点、双精度、八位字节和字符。内联不支持以下基元类型long double、wchar、boolean、enum。

struct Dimension {

int32 height;

int32 width;

}; // Inlinable

struct Dimension {

string label; // Inlinable structures cannot contain strings

int32 height;

int32 width;

}; // Not Inlinable

  • 如果任何初始对齐方式1、2、4、8大于结构的第一个成员的对齐方式则属于MyStruct的成员之间没有填充。要应用此规则请考虑图元类型的这些对齐方式和大小

表7.1图元类型的对齐和尺寸

基本类型

对齐方式字节

大小字节

int8

1

1

uint8

1

1

int16

2

2

uint16

2

2

int32

4

4

uint32

4

4

int64

8

8

int64

8

8

float

4

4

double

8

8

octet

1

1

char

1

1

struct Dimension {

int32 height;

int16 width;

}; // Inlinable. Independently of the alignment of the starting memory address (4 or 8),

there is no padding between height and width

struct Dimension {

int16 height;

int32 width;

}; // Not Inlinable. Starting in a memory address aligned to 4 will require adding a

padding of two bytes between height and width

  • 如果任何初始对齐方式1、2、4、8大于结构的第一个成员的对齐方式则MyStruct数组的元素之间没有填充。

struct Dimension {

int32 height;

int16 width;

}; // Not inlinable. Let's assume an array of two dimensions Dimension[2]. If the array

starts in a memory address aligned to 4, there would be padding between the first and the

second element of the array

struct Dimension {

int32 height;

int16 width;

int16 padding;

}; // Inlinable

出于序列化和反序列化的目的代码生成器将把可内联结构根据前面的规则视为基元数组其中基元类型的对齐方式对应于结构的第一个成员的对齐方式。类型为“MyStruct”的成员将使用单个副本memcpy调用进行序列化。

当代码生成器序列化数据结构的成员时如果可能它还将尝试将连续基元成员的序列化合并为单个复制操作。代码生成器仅在下一个成员的对齐等于或小于当前成员的对齐时应用此优化。

struct Dimension {

int16 height;

int32 width;

}; // Coalescing not possible because the alignment of width 4 is greater than the alignment of height 2

struct Dimension {

int32 width;

int16 height;

}; // Coalescing is possible because the alignment of width 4 is greater than the alignment of height 2

6.2.4 指南

根据经验要利用仅包含基本类型的类型的优化级别2

  • 按降序排列成员这将有助于复制合并。

  • 对于XCDR版本2封装如果您的类型不会演变请使用@final扩展性。对于XCDR版本1封装如果可能请使用@final或@appendable这将有助于内联扩展。

  • 如果使用ContentFilteredTopics建议将筛选器表达式中出现的字段放在类型的开头。

7 提升性能

如果需要使用不同的参数和/或类型文件多次调用代码生成器Code Generator则每次调用代码生成器时加载Java虚拟机JVM和编译速度模板都会导致性能损失。如果是这样的场景可以在服务器模式server mode下运行代码生成器Code Generator以避免多次执行此过程。或者如果您希望减少JVM启动和执行时间请使用代码生成器Code Generator提供的JVM优化机制以减少代码生成时间。

这两个选项服务器模式server mode和JVM优化不能一起使用。

7.1 使用服务器模式server mode

提高性能的一种方法是在服务器模式server mode下运行代码生成器Code Generator。服务器模式运行本机可执行文件该可执行文件打开与代码生成器的服务器实例的TCP连接该代码生成器在第一次运行可执行文件时生成如下所示

要在服务器模式servermode下调用代码生成器请使用脚本rtiddsgen_server.bat该脚本位于scripts目录中。

CodeGenerator服务器连接到的默认端口是14662。如果要修改Code Generator服务器连接到的端口请使用-n_serverport<port>参数。请注意代码生成器服务器最多可以使用三个端口确保在指定端口之后有两个可用端口(如14663和14664)。

代码生成器服务器提供了一个日志到文件选项您可以使用参数-n_logfilepath<log directory>来启用该选项。在指定的日志目录中代码生成器服务器将创建一个名为CodegenServerLog<portNumber>.txt的文件其中包含来自服务器端的所有日志消息。

代码生成器服务器带有内置超时builtintimeouts其中一些超时可以更改

  • 当代码生成器在服务器模式server mode下使用时JVM在服务器启动时加载一次速度模板也是一次性编译的。服务器将等待最多5秒以初始化代码生成器。您可以通过使用参数-n_connectiontimeout<timein millises>指定毫秒数来更改此值。

  • 如果代码生成器服务器Code Generator server在一定时间内未被使用即如果它没有收到任何呼叫则它将自动停止。默认值为20秒您可以通过编辑rtiddsgen_server脚本并调整参数-nservertimeout的值来更改这一点。

  • 代码生成器服务器Code Generator server在接受连接后向客户端发送握手handshake消息。在客户端中等待握手消息时会超时。如果客户端在短时间内10秒一个无法更改的内部值未收到此消息则代码生成器客户端将超时。此超时可能意味着端口中正在运行另一个应用程序。

注意

  • 不支持混合不同版本的代码生成器服务器Code Generator server。请参阅RTI代码生成器发行说明中的限制。

  • 代码生成器服务器Code Generator server无法并行化。代码生成器服务器的每次执行都连接到接收请求的端口并且每次只能为一个请求生成代码。所以若您尝试同时发送多个请求代码生成器服务器将按顺序处理它们。

7.2 使用JVM优化

Java虚拟机JVM提供了不同的选项有助于提高其性能。RTI在创建代码生成器JVM时应用了其中的一些选项从而提高了代码生成器Code Generator的执行时间。由于这些选项是非标准的因此默认情况下将禁用它们。如果您使用的是Connext DDS附带的JRE则可以启用这些选项否则启用这些选项的风险自负。

应用于代码生成器JVM的选项如下

-XX:+TieredCompilation

-XX:TieredStopAtLevel=1

-XX:CICompilerCount=4

-Xverify:none

-XX:+UseParallelGC

-XX:+OptimizeStringConcat

-XX:CompileThreshold=5000

有关这些选项的更多信息请参阅JDK文档

https://docs.oracle.com/en/java/javase/11/ 。目前您可以在“创建和构建应用程序的主要工具Main Tools to Create and Build Applications”>“java”中找到“工具参考”中描述的大多数选项。

若要启用与代码生成器JVM选项相关的性能改进请将RTIDDSGEN_JVM_OPTIONIC环境变量设置为true。要禁用改进请取消设置环境变量。默认情况下未设置。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6