-
Notifications
You must be signed in to change notification settings - Fork 71
Description
Feature request
Feature description
In order to reduce dynamic memory allocations during publish and receipt of messages during the operation of a Node, this API would ideally allow for users of the RMW API to request the middleware to preallocate memory for predefined message types and sizes.
Implementation considerations
Implement a struct that hides the implementation of the buffer allocation that future calls to publish
will take as an argument. If a publisher is called with the argument, then it will use the previously-allocated buffer rather than allocating a new one as necessary.
typedef struct RMW_PUBLIC_TYPE rmw_publisher_allocation_t
{
const char * implementation_identifier;
void * data;
} rmw_publisher_allocation_t;
typedef struct RMW_PUBLIC_TYPE rmw_subscription_allocation_t
{
const char * implementation_identifier;
void * data;
} rmw_subscription_allocation_t;
These can then be used by the rmw_publish
and rmw_subscription
methods to provide a reserved space for serializing/deserializing incoming/outgoing messages.
Before any messages were publish
or take
, these would need to be initialized via an API as follows:
rmw_init_publisher_allocation_t(rmw_publisher_allocation_t*, const rosidl_message_typesupport_t*, const rosidl_message_bounds_t*);
rmw_init_subscription_allocation_t(rmw_publisher_allocation_t*, const rosidl_message_typesupport_t*, const rosidl_message_bounds_t*)
rmw_fini_publisher_allocation_t(rmw_publisher_allocation_t*);
rmw_fini_subscription_allocation_t(rmw_subscription_allocation_t*)
This will also required additional information from the typesupport to get the serialized message sizes, also taking into account the potential size of unbounded fields. To account for unbounded fields, I propose adding a second structure rosidl_message_bounds_t
that will give the user a way of specifying known fixed bounds for unbounded messages.
For fixed and bounded sized messages, the API should take a const rosidl_message_typesupport_t*
which will then be allocated by the RMW implementation.
The rosidl_message_bounds_t
structure would be on a per message basis and describe any of the unbounded fields. Besides the nominal case, there are three main cases to handle.
# Message with unbounded primitive
uint8[] data
struct Msg__bounds {
size_t data__length = 0;
};
# Message with string array
string[] data
# special structure for delimiting string bounds
struct string__bounds {
size_t bounds = 0;
};
struct Msg__bounds {
size_t data__length = 0;
string__bounds data__bounds;
};
# Message with unbounded array of complex structures
std_msgs/Header header[]
# special structure for delimiting string bounds
struct string__bounds {
size_t bounds = 0;
};
struct std_msgs__msg__Header__bounds {
string__bounds frame_id__bounds;
};
struct Msg__bounds {
size_t header__length = 0;
std_msgs__msg__Header__bounds header__bounds;
};
Serialized length can be retrieved via:
rmw_get_serialized_length(const rosidl_message_typesupport_t*, const rosidl_message_bounds_t*);
These structures can then be used in conjunction with rmw_publisher
:
rmw_publisher_allocation_t alloc;
rmw_init_publisher_allocation(&alloc, ts, bounds);
# TODO: What happens when ros_message violates bounds given?
rmw_publish(publisher, ros_message, alloc);
# Also rmw_publish_serialized_message()
Or with rmw_subscriber
:
rmw_subscription_allocation_t alloc;
rmw_init_subscription_allocation(&alloc, ts, bounds);
rmw_create_subscription(node, ts, topic, qos, ignore_local, alloc)
# TODO: What happens when incoming message violates bounds?
rmw_take()
Open Questions:
- What do we do when a message violates bounds?
- Drop message
- Error and allow a retry
- Realloc and retry