micro-ROS' memory profiling is out!

A comprehensive analysis of the memory footprint of micro-ROS is available!

The full report can be found here.

micro-ROS targets microcontrollers, that is, systems with critically finite memory and processing resources. As such, a fundamental step towards fostering an ever broader adoption of this library is to assess how much of these valuable resources it consumes.

As a follow-up of a previous analysis addressing the memory usage of micro-ROS’ default middleware Micro XRCE-DDS, we now came up with an analysis of the memory consumption of the whole micro-ROS stack, taking into account all the rest of abstractions layers all the way up to the end user API.

We performed the measurements for micro-ROS apps running on FreeRTOS and on an ESP32 board connected by either UDP (via WiFi) or serial transport (UART) to a micro-ROS Agent running on a Linux machine.

We have explored both pub/sub and client/service applications. We went through several experimental setups by tuning key parameters such as topic size, entity number, history size and transport protocol. Also, we report both on the total memory and on how it is distributed between its static, stack and dynamic constituents as it is key to assess how much of each type of memory micro-ROS consumes, especially for what concerns real-timeness and determinism in its behaviour.

As an appetizer, find below the results obtained for the total memory consumption of pub/sub applications with variable entity number and topic size, with default paremeters (XRCE_history = RMW_history = 4, MTU = 512 B) and on UDP transport:

Summing up the most relevant results:

  • A publisher app with default configuration parameters and with both transport protocols explored consumes ~ 400 B of total memory, which corresponds to the memory needed for creating the entity.
  • A subscriber app with default configuration parameters and with both transport protocols explored consumes ~ 8700 B of total memory, which represents the sum of the memory needed for creating the entity and the static buffers allocated to store and handle the messages. Thanks to micro-ROS’ high configurability, this number can be heavily reduced to fit use cases with a lower memory profile.
  • A single client/service app with default configuration parameters on UDP transport consumes ~ 8800 B of total memory. This reflects the fact that, in a request/response pattern, messages need to be stored and handled as in the subscription case.

Note: The handling of the RMW history for subscriptions and services, which are the most critical cases, can be revisited in order to reduce the growth of the static consumption. The current implementation reserves a memory of RMW_history * XRCE_history * MTU for each subscriber/client/service. Our most recent considerations are directed towards reducing this number by using a shared RMW history pool for every entity.

6 Likes

As a result of the many refactorizations and improvements micro-ROS went through lately (see e.g. here and here), the whole stack comes now a whole different -significantly smaller!- memory footprint.

More concretely, the implementation of shared memory pools for entities to handle the RMW static memory, as compared to the previous paradigm, based on a per entity allocation of pools, is what allows those entities in need to receive data (subscribers, clients, and servers) to save quite a lot of memory.

To grasp an idea of the order of magnitude of the memory saving, it’s useful to compare the new set of results obtained by performing the same measurements we performed back in October, and check the consumption of the most critical cases.

Find the whole updated article here and below three comparisons of representative results:

  • The first plot shows the comparison between the total memory used by a variable number of subscribers ranging from 1 to 15 in the old (left column) and new (right column) configurations in both Reliable (first row) and Best-Effort (second row) modes, for a variable size of topics. The communication with the Agent is done over UDP WiFi transport, the MTU is 512 B, and the number of pools (RMW history) is 4 for each entity in the old configuration, and 8 shared between all entities in the new configuration.

  • The second plot shows the comparison between the stack, static, and dynamic memories used by a variable number of subscribers ranging from 1 to 15 in the old (left column) and new (right column) configurations in both Reliable (first row) and Best-Effort (second row) modes, for a topic size of 1 B. The communication with the Agent is done over UDP WiFi transport, the MTU is 512 B, and the number of pools (RMW history) is 4 for each entity in the old configuration, and 8 shared between all entities in the new configuration.

  • The third and final plot shows instead the comparison between the stack, static, dynamic, and total memories used by either servers (first row) or clients (second row), in a variable number ranging from 1 to 10, in the old (left column) and new (right column) configurations, and for a topic size of 1 B. The communication with the Agent is done over UDP WiFi transport, the MTU is 512 B, and the number of pools (RMW history) is 4 for each entity in the old configuration, and 8 shared between all entities in the new configuration.

7 Likes

That’s an impressive memory consumption drop for the micro-ROS stack!