Skip to content

feat: Cache internal string 3x speedup - #265

Open
jmachowinski wants to merge 2 commits into
rollingfrom
jm_optimizations
Open

feat: Cache internal string 3x speedup#265
jmachowinski wants to merge 2 commits into
rollingfrom
jm_optimizations

Conversation

@jmachowinski

Copy link
Copy Markdown

Description

AI experiment to speed up serialization.

Fixes # (issue)

Is this user-facing behavior change?

No

Did you use Generative AI?

Yes, claude sonet

Additional Information

Draft for now

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>
  ``convert_to_py`` now allocates the Python message directly and writes to the
  ``_field`` slots instead of calling the class and assigning through the property
  setters. ``__init__`` used to recursively construct a default value for every
  field, all of which were immediately overwritten. ``convert_from_py`` reads the
  slots directly for the same reason. On a ``visualization_msgs/MarkerArray`` with
  500 markers holding 200 nested elements each, ``convert_to_py`` went from 110 ms
  to 30 ms and ``convert_from_py`` from 22 ms to 9 ms.

  Behavior change: because the property setters are bypassed,
  ``ROS_PYTHON_CHECK_FIELDS=1`` no longer runs its type assertions when a message is
  converted from C to Python. It still applies to messages that user code constructs
  or assigns to. The values produced by the conversion are built by the generated C
  code itself and cannot have the wrong type.

Assisted-by: Claude Opus 5
@jmachowinski

Copy link
Copy Markdown
Author

Pulls: #265
Gist: https://gist.githubusercontent.com/jmachowinski/2ba742a18b0b1166e0c1e328d2204174/raw/85aef965f048ca0843569b031a1e15281bbe679e/ros2.repos
BUILD args:
TEST args:
ROS Distro: rolling
Job: ci_launcher
ci_launcher ran: https://ci.ros2.org/job/ci_launcher/20162

  • Linux Build Status
  • Linux-aarch64 Build Status
  • Linux-rhel Build Status
  • Windows Build Status

@jmachowinski

Copy link
Copy Markdown
Author

I retested this with a ping pong test of visualization markers.
Without the patched I get 40 msg/sec and my ryzen 7800 X3d maxes out at 100% cpu load.
Time to publish a msg is 4.6ms (note recv is WAY worse)

With this patches I get 60 msg/sec at 20% cpu load
Time to publish a msg is 1.2ms (cpp 0.160 ms)

@jmachowinski
jmachowinski marked this pull request as ready for review August 22, 2026 12:16
@mergify

mergify Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

@wjwwood wjwwood left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat, seems reasonable to me. May need more acceptance testing and/or review. I didn't dive too deep.

PyObject * pymessage_class = PyObject_GetAttrString(pymessage_module, "@(message.structure.namespaced_type.name)");
assert(pymessage_class);
if (pymessage_module == NULL) {
return NULL;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the deleted code they were using asserts, and I don't know which is more appropriate here but I'd like to know if this results in a behavior change or not. I would think this would change how python handles the result.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In release mode this would simply crash if pymessage_module is null.
In debug mode you would get an assert failed.

According to the AI return NULL will cause an exception later in the rclpy code.

I can reintroduce the asserts for debugging...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants