DDS_DynamicData_get_serialized_size problem

5 posts / 0 new
Last post
Offline
Last seen: 6 years 8 months ago
Joined: 04/04/2014
Posts: 27
DDS_DynamicData_get_serialized_size problem

Hello!

UPDATE: I had a copy paste mistake in my tests when I was looking for a right method to get serialized size of dynamic data. I've updated post correctly. Function works as it should, however I still don't understand the meaning of the values.


One of DDS usecases involves serializing and deserializing DynamicData objects. I was looking for a method to get size of serialized representation and  DDS_DynamicData_get_serialized_size looked like good guess, but it seems that there is something strange problem with this method. According to the source code of this function, it makes nothing else but calls  DDS_DynamicData_get_serialized_size_ex (if self->_buffer.parametrizedBuffer== 0 and it's my case) so my expectation was that both functions provide the same result. As another solution to get size I've found another method - DDS_DynamicDataBuffer_get_data_size. I've made tests with two typecodes - one with constant size and another with sequence. As expected value I've took  RTICdrStream_getCurrentPositionOffset() after calling DDS_DynamicData_to_stream()

Constant sized type:

  • serialized_min_size/serialized_max_size: 568/568
  • DDS_DynamicData_get_serialized_size: 1136
  • DDS_DynamicData_get_serialized_size_ex (last parameter set to FALSE): 568
  • DDS_DynamicData_get_serialized_size_ex (last parameter set to TRUE, as in source code): 1136
  • DDS_DynamicDataBuffer_get_data_size: 568
  • Expected value: 568

Type with sequence:

  • serialized_min_size/serialized_max_size: 20/10000020
  • DDS_DynamicData_get_serialized_size: 1040
  • DDS_DynamicData_get_serialized_size_ex (last parameter set to FALSE): 1020
  • DDS_DynamicData_get_serialized_size_ex (last parameter set to TRUE, as in source code): 1040
  • DDS_DynamicDataBuffer_get_data_size: 1020
  • Expected value: 1020

 

Offline
Last seen: 3 weeks 3 days ago
Joined: 01/10/2013
Posts: 31

Hi, 

The meaning of those various values are as follows:

  • DDS_DynamicData_get_serialized_size: Returns the serialized size of the current dynamic data object, taking into account a parameter header that is added to the type during serialization, dependent on whether the type is mutable or optional members. In those cases  we need to add a parameter header to the type during serialization, increasing the serialized size of the sample.
  • DDS_DynamicData_get_serialized_size_ex (last parameter set to FALSE): Does not add room for the parameter header described above
  • DDS_DynamicData_get_serialized_size_ex (last parameter set to TRUE, as in source code): Does take into account the parameter header described above
  • DDS_DynamicDataBuffer_get_data_size: gives the actual value of the DynamicDataBuffer at that moment. If the type does not need any parameter headers added during serialization then this is the size of the serialized sample that will be sent, otherwise, it will be the value returned from DDS_DynamicData_get_serialized_size_ex with the last parameter set to TRUE

 

Also, where are the values for serialized_min_size/serialized_max_size comine from? 

Please let me know if any of that is not clear. 

Offline
Last seen: 6 years 8 months ago
Joined: 04/04/2014
Posts: 27

Thank you for your explanation! Could you give some more details about parameter header?

  • Is my understanding correct, that parameter header is appended if some of the fields are defined as mutable or extensible (not final)?
  • Does DDS_DynamicData_get_serialized_size return the size of the data which will be sent over the network? In my first example to_stream method will write only 568 bytes to the CdrStream though DDS_DynamicData_get_serialized_size returns 1136. These 1136 bytes are 568 bytes to encode the data currently in DynamicData object + conservative value for the parameter header equal to "serialized size of a sample initialized with default values". Does it mean that there is additional overhead when sending data with mutable or extensible fields?

min/max sizes are coming from these private functions:

unsigned int DDS_TypeCode_get_type_serialized_max_size(const DDS_TypeCode *type, RTIBool include_encapsulation, /* ignored */ RTIEncapsulationId encapsulation_id, unsigned int current_alignment);
unsigned int DDS_TypeCode_get_type_serialized_min_size(const DDS_TypeCode *type, RTIBool include_encapsulation, RTIEncapsulationId encapsulation_id, unsigned int current_alignment, DDS_Boolean use_default_union_member);

Offline
Last seen: 3 weeks 3 days ago
Joined: 01/10/2013
Posts: 31

You're welcome!  

There is a good explanation of what exactly goes on the wire in the RTI_CoreLibrariesAndUtilitie_GettingStarted_ExtensibleTypesAddendum.pdf in you NDDSHOME/doc/pdf directory, Chapter 4 "DataRepresentation". To summarize though, in the case of final and extensible types, we use the traditional OMG CDR representation ot serialize the data (no parameter header), but in the case of optional members and mutable types we use Extended CDR (an extension to the OMG CDR representation), which is when the parameter header gets used. So yes, there is extra over head when sending mutable data or data with optional members. 

It would help me to understand what's going on if you could tell me the exact types that your using in these two scenarios, but yes--the DDS_DynamicData_get_serialized_size will return a conservative number, including room for the parameter header that may need to be added in the case of mutable types or the existence of optional members in your type. 

 

Offline
Last seen: 6 years 8 months ago
Joined: 04/04/2014
Posts: 27

The types are:

 struct struct1{
    sequence<octet,10000000> data;    //@ID 0
    double timestamp;    //@ID 1
    unsigned long id;    //@ID 2
};
//@Extensibility EXTENSIBLE_EXTENSIBILITY

struct struct2{
    boolean field00;    //@ID 0
    boolean field01;    //@ID 1
    boolean field02;    //@ID 2
    boolean[7] field03;    //@ID 3
    boolean[7] field04;    //@ID 4
    boolean[7] field05;    //@ID 5
    boolean[7] field06;    //@ID 6
    double[7] field07;    //@ID 7
    double[7] field08;    //@ID 8
    double[7] field09;    //@ID 9
    double[7] field10;    //@ID 10
    double[7] field11;    //@ID 11
    double[10] field12;    //@ID 12
    boolean[7] field13;    //@ID 13
    boolean[7] field14;    //@ID 14
    boolean[7] field15;    //@ID 15
    boolean[7] field16;    //@ID 16
    boolean[10] field17;    //@ID 17
    double[7] field18;    //@ID 18
    double[10] field19;    //@ID 19
};
//@Extensibility EXTENSIBLE_EXTENSIBILITY

RTI Admin Console shows that struct struct1 is extensible, field data is mutable, remaining fields are final. struct2 itself is extensible, all members are final.

Thanks for pointing to the ExtensibleTypesAddendum, it explains appending header quite well, but I think it's little confusing that  get_serialized_size always returns size with parameter header even if it's not needed. I think the solution is to use logic from  DDS_DynamicDataTypePlugin_get_serialized_sample_size and call

DDS_DynamicData_get_serialized_size_ex(data, DDS_DYNAMIC_DATA_ENCAPSULATION_KIND_DEFAULT, 
	DDS_TypeCode_has_mutable_aggregation_type(tc, &ex) || DDS_TypeCode_has_optional_members(tc, &ex));