Well, it would also introduce a dependency on fmt right? That would be my hesitation, but given its value it might be worth doing.
Maybe we’re using different meanings for these terms, so what does “negative overhead” mean in this case? Maybe “negligible overhead”?
Also, perhaps a technical question, but how does fmt achieve zero-overhead when not using macros. The reason we use macros in our API is so that they can be completely compiled out by defining an empty macro when configured to build that way.
Finally, does anyone have insight on how complete a replacement for fmt the new C++20 std::format is? We cannot use it yet, but it will hopefully be in reach of the core library soon.
I would love to see changes to rclcpp which let you use fmt with it, but without depending on fmt, and then later use it with std::format when that is available. Maybe that’s not a reasonable path forward for technical reasons, but just thinking out loud.
That all being said, putting a feature like this into a separate package and letting it get use/polish before trying to include it in a core package like rclcpp, is definitely the right way to go, so thanks for doing that, it looks cool.
I think the overhead here is related to the arguments of the logging call. With a logging library, you want to completely skip argument evaluation if a log level is disabled. Can templates achieve that?
RCLCPP_DEBUG(node->get_logger(), "%s", very_expensive_func_to_summarize_a_point_cloud(point_cloud));
In the first case if you decide to compile out debug log statements then neither the get_logger() function (could incur a string copy) nor the summarize function are called. In the second case, though the fmt function is not called, the other two functions are called.
Yes, but it’s behind the rcl_logging abstraction, so you could configure your system to instead use the rcl_logging_noop that does nothing and then you don’t need spdlog. If we expose this to the user API, then you have a hard dependency on either fmt or something like std::format. I’m not saying that’s a bad thing, just that it’s different then the logging backend which is swappable.
Maybe you could verify if templates don’t have a way to achieve the same zero-cost when a debug level is disabled. Since they work in compile time, they could at least theoretically have the ability (it’d be interesting to see the assembler when compiled with and without optimizations).
The only reason I am aware of this need is because it has caused performance problems in rviz’s point cloud rendering before:
It boiled down to an expensive debug statement inside the pointcloud rendering inner loop that was removed when compiling with -DNDEBUG, which controlled whether or not debug logging statements were included.
Not exactly the same, but an example nonetheless of how the ability to not only remove the logging message but the work done to produce it was important as a compile time constraint.