I recall some of us from SIG-NG chatted about this at ROSCon, but I
don't remember everyone who was there (some combination of Jack,
Geoff, William, and Mike Purvis, maybe?). So I figure I'll just email
everyone, and anyone can jump in...
I've been thinking about how I'm going to follow up the real-time work
to make the full intra-process pipeline and the service/client
pipeline real-time safe in rclcpp.
In the current implementation, the MemoryStrategy class handles
preallocated pools of memory that need to get instantiated during
RT-runtime. These pools are simply arrays of the specific classes that
must get instantiated, such as the AnyExecutable class.
The advantages of this approach are that it's simple and easy to
engineer, and actually pretty good for performance--by using
preordained knowledge about the execution of the program, we can
reserve exactly as much memory as we need. However, the performance
tradeoff is that we don't reuse those reserved pools of memory when we
don't need them, which could be possible in a smarter allocator. The
bigger disadvantage is that it creates a lot more code to write and
maintain.
I am considering moving to the approach of exposing an allocator
interface as a template argument to several classes in rclcpp, and
setting the default to std::allocator [1], then providing at least one
O(1) allocator as an alternative to the default.
It's a more elegant and generalized approach than the MemoryStrategy,
but harder to implement. It would be trivial if we could just package
an existing real-time safe allocator in rclcpp. But it's actually
quite hard to find a good allocator that's appropriate. TLSF [2] is an
allocator specialized for embedded systems. Heap Layers [3] is an
awesome library of composable "allocator primitives". But both are
under GPL licensing, and we want to release ROS 2 under Apache 2.
Also, using allocators that follow the std::allocator interface means
that those allocators could be passed to STL structures like vector
and map that are used in rclcpp and can incur allocation penalties
What I might do is explore the allocator interface approach and use
these existing allocator implementations for testing, but not include
them anywhere in the ROS 2 codebase to avoid GPL. Then, if I decide
the approach is viable/better than MemoryStrategy, I will pursue an
existing allocator that is LGPL or Apache, or implement my own to be
included with ROS 2.
Let me know if you'd like clarification about anything--there might be
some context missing for people who haven't looked extensively at the
rclcpp codebase, or anyone who isn't familiar with std::allocator and
std::allocator_traits.
Cheers,
Jackie
p.s. The TLSF implementation is in C anyway, so I will have to modify
it slightly to make it work with std::allocator_traits.
1.
http://en.cppreference.com/w/cpp/memory/allocator
2.
http://www.gii.upv.es/tlsf/main/repo
3.
http://heaplayers.org/