Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add improvements to the custom types section in doc #331

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

javmorcas
Copy link
Member

This pull request is coming from the issue #327. When the pull request is merged into "master" the issue will be [resolved, closed, fixed] #XX

Comment on lines 7 to 11
*RTI Perftest* allows the user to add their own `idl` types, instead of using
the one provided by default. The purpose of this feature is to get a closer
approximation to the performance behavior of the user's final system. The main
reason why using one type or another will result in different outputs for latency
and throughput is the serialization and deserialization times.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RTI Perftest allows the user to test the performance of their own datatypes defined via 'idl', instead of
the one provided by default. The purpose of this feature is to get a closer
approximation to the performance behavior of the user's final system. The main
reason why using one type or another will result in different results for latency
and throughput is that serialization and deserialization performance depends on the complexity of the datatype.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By the way, is the testing of customDatatypes only supported in traditional C++? Not in C, Modern C++ or Java? If that is the case, should state that here as well.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

reason why using one type or another will result in different outputs for latency
and throughput is the serialization and deserialization times.

This feature is designed to work for regular data, *DynamicData*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feature is designed to work for regular data, DynamicData
and FlatData type definitions (required to test Connext DDS FlatData and/or Shared Memory Zero Copy features).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment on lines 16 to 19
**Note 1:** For *DynamicData*, the way this is implemented is by representing the data
as a regular *idl* generated type, and then, internally use the *DynamicData*
type support representation equivalent for that type as well as build the samples
with the *DynamicData* API. Hence, providing the *idl* structure is required to the user.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DynamicData testing uses the Connext DDS DynamicData API to serialize/deserialize/copy and otherwise manipulate a data structure instead of compiled type support-generated functions from the user's type definition file. However, for Perftest to do this with a user's datatype, the user must still provide their datatype definition in an idl file with which DynamicData will use a compiled/generated function to access the typecode for the datatype.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

below.

To simplify testing using this feature. Some working examples can be found and
used under `resource/exaples_customType`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The simplest way to begin testing your own types is to begin with the working example found in 'resource/examples_customType'. You can copy the examples and modify the example IDL with your own datatype definition for the various testing scenarios, regular, DynamicData, FlatData (needed for Zero Copy).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment on lines 21 to 23
**Note 2:** The use of *Flat Data* requires the generation of a regular type as
well due to the current implementation. See especific notes in a dedicated section
below.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note 2: To test Flat Data serialization/deserialization of user data types requires the user to define both a regular datatype and a FlatData variant. See specific notes in the section Custom Types + FlatData below.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment on lines 31 to 32
*RTI Perftest* default type resembles the following (with some variations depending on
the use of *Keyed data*, *Flat Data*, *Unbounded Types* or *Zero Copy*):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RTI Perftest default datatype

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

sequence<octet, MAX_BOUNDED_SEQ_SIZE> bin_data;
};

However, in order to use a given type, the struct has been modified as follows:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, in order to use an user-specified datatype,

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

long timestamp_sec;
unsigned long timestamp_usec;
long latency_ping;
sequence<octet, MAX_BOUNDED_SEQ_SIZE> bin_data;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to me that can remove this member if custom data is being used, so something like
#ifndef RTI_CUSTOM_TYPE
sequence<octet, MAX_BOUNDED_SEQ_SIZE> bin_data;
#endif

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is something we can study. I will work on it in a different branch

};

Notice that a `RTI_CUSTOM_TYPE` member has been added to the struct (conditionally).
This placeholder is replaced at generation time with the type specified by the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This macro is replaced

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

long test_long; //@key
};

The type Name needed for `RTI_CUSTOM_TYPE` will be `Test` (independently
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Users must supply the name 'Test' to the perftest build process as the name of their customType so that 'RTI_CUSTOM_TYPE' will be replaced by 'Test'.

Not sure if "(independently on the name of the file where the struct is, or if it is preceeded or followed by
other structures)." is useful or (even understandable at this point in the doc)". I would probably delete it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


The steps needed to use a custom type in *RTI Perftest* are:

Copy the IDL files into `~/rtiperftest/srcIdl/customTypes/`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy the IDL file(s) used to define the user's datatype to be tested into ~/rtiperftest/srcIdl/customTypes/.

Even though a datatype may require multiple IDL files to fully define the type and all of its contained members, perftest can only be compiled to test a single user datatype at a time. You may build different images of perftest to test different user datatypes by supplying a different customType name at build invocation.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

There are some restrictions for this step:

- You can include multiple `.idl` files, but all of them should be at the same
level (no folders are allowed inside the `customTypes` folder.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing end ')'

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

level (no folders are allowed inside the `customTypes` folder.
- The `idl` files cannot be named `custom.idl`. A file with this name will be generated
automatically by the `build` script, so this file would be overwritten.
- The main type you will link should be declared as ``struct <NameOfTheType> {``.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The customType that you want to test must be declared as in an '.idl' file as struct <NameOfTheType> {.
In the declaration, there must be only a single space character between struct and { and the name of the datatype. The build scripts will complain that they can't find your datatype definition in the '.idl' files if your datatype definition does not follow the required format.

spelling/typo: "accross" --> "across"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

initialized by the user in the `set_custom_type_data`, `set_custom_type_dynamic_data`
and `set_custom_type_data_flatdata`.

**Note:** If using *FlatData* see the dedicated section below.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: If using FlatData see the section Custom Types + FlatData below.


**Note:** If using *FlatData* see the dedicated section below.

Run the `build` script adding ``--customType <NameOfTheType``
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing ">" in "<NameofTheType"

Run the `build` script adding ``--customType <NameOfTheType``
-------------------------------------------------------------

Run the ``build.sh`` or ``build.bat`` script using the ``--customType`` option.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using the --customType <NameOfTheType> option.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The title of this section is "Run the build script adding --customType <NameOfTheType" and then the first line in this section is "Run the build.sh or build.bat script using the --customType option." Seems a bit redundant.

Recommend

Building Perftest with custom types

Run the build.sh or build.bat script with the additional --customType <NameOfTheType> option. For testing FlatData and/or ZeroCopy, please see the section Custom Types + FlatData.

Comment on lines 105 to 106
file contains several functions that must be implemented in order to correctly
initialize, finalize and populate the sample.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, the doc is stating "must be implemented", later on it's stated

"The following functions should be implemented (optionally) to properly
initialize and set the custom type structures."

I would suggest

You should find a file in ${PERFTEST_HOME}/srcCpp/customType.cxx. This
file contains several functions that may need to be implemented in order to correctly
initialize, finalize and populate the sample. Please see full discussion in the section Full example using Custom Types.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

initialize, finalize and populate the sample.

**Note:** *RTI Perftest* will not initialize by default sequences, optional members
or non-primitive structures. This means that those fields will need to be
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what "non-primitive structures" are. Do you mean "non-primitive" members? If so, do you mean members that are pointers? Does this include strings (aka "char *")? Or do you actually mean a member that's a nested structure (but not a pointer to a nested structure)?

For regular custom type testing, if the perftest code calls TestData_tTypeSupport::create_data(), wouldn't non-@optional pointers/strings, etc. of the nested user customType all be allocated? And contained sequences initialized to hold max length elements with a current length of 0?

If so, I would probably modify this to state

Note: Users must initialize or otherwise set the values of certain types of members of their custom datatype or else those members may not be sent during testing. Theses includes setting the length of sequence members (default length is 0), the values of strings (default is empty string ""), and the values of any @optional members that you want to be sent during tests. To set those values, you may need to customize the implementations of set/initialize_custom_type_data, set/intialize_custom_type_dynamic_data and/or set/initialize_custom_type_data_flatdata.


Run the ``build.sh`` or ``build.bat`` script using the ``--customType`` option.

**Note:** If using *FlatData* see the dedicated section below.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would not be needed if modification is made to the beginning of this section is adopted.

Run *RTI Perftest* as usual
---------------------------

A string at the beginning of the execution should indicate that you are using a
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To verify that perftest_cpp is testing a customType, look for output similar to this when the test is started:

RTI Perftest Master df3055c (RTI Connext DDS 6.0.1)

Custom Type provided: 'Test'

Perftest Configuration:
Reliability: Reliable
Keyed: No
...

Custom Types + `FlatData`
~~~~~~~~~~~~~~~~~~~~~~~~~

*FlatData* types are at this point in *RTI Perftest* associated to regular types.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this sentence is needed.

FlatData types are at this point in RTI Perftest associated to regular types.

~~~~~~~~~~~~~~~~~~~~~~~~~

*FlatData* types are at this point in *RTI Perftest* associated to regular types.
If you want to use *FlatData* with for your Custom Types, follow these
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to test your customType using the FlatData language binding, follow these

If you want to use *FlatData* with for your Custom Types, follow these
additional steps:

- Create a copy of your original type (which should not be `FlatData`) in the same IDL file.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create an identical copy of your customType in the same IDL file and rename the datatype, for example from "Test" to "Test_flatdata".

additional steps:

- Create a copy of your original type (which should not be `FlatData`) in the same IDL file.
- Make this new type mutable (``@mutable``) and make it FlatData compatible (``@language_binding(FLAT_DATA)``).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The FlatData version of the customType must have Mutable Extensibility and FLAT_DATA Language Binding, for example:
@mutable
@language_binding(FLAT_DATA)
struct Test_flatdata {
...

- Implement the additional API custom type functions of customtype.cxx for *FlatData* types.
This is a *must*, as the type is ``@mutable``, and every field is considered as optional
and not sent into the wire if it is not set.
- Run the build script with the command-line parameter ``--customType <type>`` and ``--customTypeFlatData <flat_type>``.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parameter --> parameters

This is a *must*, as the type is ``@mutable``, and every field is considered as optional
and not sent into the wire if it is not set.
- Run the build script with the command-line parameter ``--customType <type>`` and ``--customTypeFlatData <flat_type>``.
- Run *RTI Perftest* as usual.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Run RTI Perfest with -flatData to test using FlatData with your customType and/or -flatData -zeroCopy to test Zero Copy over shared memory with your customType.

Full example using Custom Types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The following types will be used for this example. The code can be found under
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code can be found under --> Related files can be found under

enum TestEnum {
ENUM1,
ENUM2
};//@Extensibility FINAL_EXTENSIBILITY
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest modifying this RTI-proprietary method of specifying extensibility to the standard one.

@Final

Comment on lines +175 to +176
These functions in the example are spreaded across several `idl` files to show the
multiple files capability of the feature.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the example, these definitions are spread across several idl files to demonstrate the ability of perftest to use multiple files for defining a customType.

multiple files capability of the feature.

These are the steps needed to use the above type in *RTI Perftest* for the
C++ (Traditional) API:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By making this statement, it begs the question, how do I do it for other languages, C, C++ (Modern), Java. If they are not supported, then this statement is better phrased:

The following steps are used to build and run RTI Perftest to test the customType Test defined above. Note, the testing of customTypes is only supported using the DDS C++ (traditional) API.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The following types will be used for this example. The code can be found under
``resource/examples_customType/no_key_large``.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion, this isn't a great example to document...it's not really a "Full example". It's not a keyed datatype nor does it show flat data.


1. Copy all the `idl` files into the `srcIdl/customType/` folder.

2. The following functions should be implemented (optionally) to properly
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file resource/examples_customType/no_key_large/srcCpp/CustomType.cxx has been customized to implement some required functions needed to initialize members of the data structure. For your own customType, you would modify the implementations of the functions in "rtiperftest/srcCpp/CustomType.cxx" as required. To test the type defined in the example resource/examples_customType/no_key_large/, you only need to overwrite rtiperftest/srcCpp/CustomType.cxx with ```resource/examples_customType/no_key_large/srcCpp/CustomType.cxx``.

Comment on lines +187 to +189
This function is used to initialize your data.
Using this function, you will be able to allocate memory or set an immutable
field of the data.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is called once to initialize the instance of your datastructure sent during the test.
Using this function, you will be able to allocate memory or set an immutable field of the data.

Use this method to set any @optional members that you want to be sent.
Use this method to set a fix length of sequence members.
Use this method to set a fixed value of any string members.

bool initialize_custom_type_data(RTI_CUSTOM_TYPE &data)
{
bool success = true;
if (!data.test_seq.test_seq.ensure_length(SIZE_TEST_SEQ, SIZE_TEST_SEQ)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite understand why this example is setting a compiled-in, non runtime changeable length for the sequence. It seems that the string member should be initialized here. And the length should be set in the set_custom_type_data() method.

}

- **register_custom_type_data**
This function is used to set your data before being registered. It is only
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand the use and thus requirements for this function.

So this is only needed for tests using keys, which would use the TestDataKeyed_t (and variants)?

So, for a keyed test, the test will create keys in the form of unsigned long values that this function will need to store into the key fields defined by the user data type if it is defined with a key field(s)? Is that the idea? But why is this needed? Since the octet key member is still a key member, couldn't the test framework just continue to set that value itself without requiring setting of any key members inside the user structure and still create the number of instances required for the test?

In short, I don't think this function is required to support the testing of keys when using user data types...

The function takes three arguments:

- A reference to custom type data.
- A specific number unique for every key.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, I'm not sure that there's any additional functionality added with this key argument. The key value could have just been set by the test framework in it's own "key" member and not rely on this method to set a key value in the customType.

Comment on lines +226 to +227
You must set the custom type data before it is sent with the right
"key" value and the "targetDataLen".
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"You must implement this method if you want perftest to dynamically set the sizes of the variable length members of your data structure such as sequences or strings."

Do they also need to set @optional members here? Or can they just set those once in the initialize function?

We need to also make a statement that all members, sequences or not, optional or not, need to be set for the FlatData case (and show example code). Should have an example for the FlatData usecase, more common than DynamicData I think. See my very last comment.

}

- **finalize_custom_type_data**:
This function is used to remove your data. It is called in the destructor.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm actually unsure why this finalize is needed? Only if you're running some sort of memory checker/validation software for memory leaks?

Yes, it is programming "correctness" to have such a function. But practically, speaking, there's no reason to implement this. Having it available is mostly just wasted effort (by us to support/document it) other than satisfying those folks who are OCD...

Comment on lines +269 to +271
This function is used to initialize your DynamicData.
Using this function, you will be able to allocate memory or set an immutable
field of the data.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comments as for initialize_custom_type_data.

{
bool success = true;
data.test_long = key;
if (sprintf(data.test_string.test_string, "Hello World! %lu", key) < 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would switch this with the contents of initialize. The string should have been set once. There's really no reason to set the test_string, over and over again. It's not a key...well, I guess it would be in the key test since the "Test" struct itself has no keys, and the TestDataKeyed_t struct declares the nested "Test" struct as keyed, and thus all members are part of the key. But that's not the point. The point is that the embedded string probably should only need to be initialized once (sprintf is pretty expensive to call, and the test isn't really supposed to be measuring the cost of setting the value of the data being sent).

On the other hand, this would be the logical place to use the targetDataLen to set the length of the sequence member.

Comment on lines +314 to +315
Set the custom type data before it is sent with the right "key"
value and the "targetDataLen".
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comments as in set_custom_type_data.

fprintf(stderr, "set_long(test_seq) failed: %d.\n", retcode);
success = false;
}
retcode = customTypeData.unbind_complex_member(testSeqData);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the unbinding required to finalize the setting of the data?

If so, would be useful to have a comment making that statement. Not sure how familiar people will be with the proper usage of the DynamicData API (I myself am a neophyte in this respect).

Comment on lines +511 to +512
5. You can also launch *RTI Perftest* with your customType using DynamicData.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this mode, Perftest will use the DynamicData API to serialize/deserialize the customType data structure instead of the generated serialization/deserialization code.

Waiting for data ...
Length: 464 Packets: 8146078 Packets/s(ave): 135770 Mbps(ave): 504.0 Lost: 0 (0.00%)
Finishing test...
Test ended.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I would probably omit the DynamicData example and use a FlatData/ZeroCopy example instead. I've not heard that customers are interested in the performance of DynamicData on their datatypes....not even sure what their use case would be myself. But certainly, I have seen interest in FlatData (and mainly ZeroCopy which requires FlatData).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants