orocos / rtt_ros_integration

Orocos-ROS integration libraries and tools

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Change the default number of spinner threads

ahoarau opened this issue · comments

The default spinner thread count for rtt_rosnode is set to 1 .

In roscpp code I see that setting it to zero gets us ths number of CPUs
https://github.com/ros/ros_comm/blob/kinetic-devel/clients/roscpp/src/libros/spinner.cpp#L207:L209

Is there any reason why this is set to 1 and not 0 ?
I had an issue on xenomai not allowing the ROS spinner thread to send anything (xeno task was taking too much ressources), which was solved setting more threads.

I agree that the number of spinner threads has a significant effect on the overall behavior of a ROS application, including ROS-enabled Orocos processes. This is especially true if the process provides services, where a long-running callback actually blocks all subscriptions.

Increasing the number of default spinner threads would be one option to mitigate the problem, and unless someone would use ROS primitives with callbacks directly within the same process or rtt_roscomm service server proxies with ClientThread operations, there should be no noticeable side effect.

We had a similar problem in the past few weeks and I was thinking about the following alternative solutions, which eventually would scale better:

  • a per subscriber or service server CallbackQueue and associated Orocos activity
  • a per component CallbackQueue and associated Orocos activity, similar to the dispatcher threads of the CORBA or mqueue transport for the sending side. Similarly the RosPublishActivity could be instantiated per component instead of as a process-wide singleton.
  • a customized implementation of ros::CallbackQueue that instead of enqueuing a callback and waiting until a spinner thread polls it would call the callback immediately. This callback would directly push the message to the data or buffer object associated with the ROS stream connection, bypassing ROS' callback queue and the spinner threads completely. Orocos RTT already has all the primitives we need. On the other hand deserialization would already happen in roscpp's network thread and I am not sure whether this is a good idea.

I could imagine option 1. would create many more activities/threads. Maybe that would be a bit too much in smaller systems. But one advantage could be to set the frequency on a particular topic (ex output state at 30Hz, incoming at 500Hz), rather than publishing/advertising at the component's frequency.

To me ,option 2. seems like the best alternative, although I honestly don't really get the implications of 3 on the data flow.

Annexe question about 2 : Could this mean that the spin could be somehow synced/shared with the execution of the component ? I'm thing about the the case where I have ROS primitives callbacks inside the component. That could be a way to simulated the client/ownthread.

Did you ever get the chance to work on this ?

Did you ever get the chance to work on this ?

No, not yet, and it is not a priority. Setting the default value of ~spinner_threads to 0 (number of CPUs) is probably the fastest and simplest solution. Feel free to open a pull request.

I created a separate issue #117 for #104 (comment).

The original request has been addressed in #116. Thanks, @ahoarau!

Thanks for the merge. I'm still facing high cpu load when a few components are publishing at high frequency. I'm hoping the 'per component' callback would solve this.