Why you shouldn’t use boost::any (especially not in time-critical code)
In case you didn’t know, boost::any is a conveniant way to store & pass any (no shit, Sherlock!) datatype you can imagine. No one would expect that such nice things work without some overhead – however the implementation of boost::any does not seem to be the fastest around, as some tests I did today show. Luckily, I remembered a stack overflow answer to some unrelated question about boost::any, pointing out that there’s an alternative for boost::any in the boost library itself, namely boost::spirit::hold_any, being smaller, faster and providing nifty stream output operators. Back then, assuming boost itself being heavily optimised, I could not imagine that the performance difference was substantial, so I dropped the idea of using boost::spirit::hold_any, hoping that if its implementation was that good it would replace boost::any sooner or later anyways. As I learned today, this assumption is simply wrong.
Using a simple testing program I evaluated the performance of boost::any, boost::spirit::hold_any and simply casting to void* and back. Needless to say, casting around void pointers is the fastest method, but you are losing any type information whatsoever and may run into bugs which are difficult to find. However, even the difference between boost::any and boost::spirit:hold_any is almost an order of magnitude! Lesson learned: if you want to use a typesafe fire-and-forget-use-any-datatype concept, stay away from boost::any and stick with boost::spirit::hold_any – their usage is essentialy the same. If you need the last bit of speed (and you have checked using a profiler that hold_any is the thing thats slowing the code down) you may want to consider entering the minefield of void pointer casting :)
Stop your jibber-jabber, here’s the real data (setting 100000000 size_t values using each method to pass the argument to a function):
|Method||g++||g++ -O1||g++ -O2||g++ -O3|
It is crucial to mention that the comparison between the boost classes and passing void pointers is only fair when using these classes only to pass parameters to functions, and not their ability to store arbitrary data – to accomplish this using void pointers one would need additional code overhead, which would certainly slow the whole thing down. The key of this article was to compare boost::any to boost::spirit::hold_any, using the void* method to introduce some baseline maximum speed.
Last but not least, here’s the code I used to evaluate the performances: test.cpp. Remove the .doc extension – WP does not like uploading .cpp files :)