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
boost::any 7.29s 3.64s 3.63s 3.21
boost::spirit::hold_any 2.93s 0.93s 0.66s 0.40
void* 0.49s 0.32s 0.05s 0.05

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 ๐Ÿ™‚

Advertisements

Tags: , , , , , , , , ,

3 responses to “Why you shouldn’t use boost::any (especially not in time-critical code)”

  1. Andrea Bocci says :

    Five years later, std::any comes to the rescue !

    Here’s what you get with the same test code, with gcc 7.1 in c++17 mode:

    boost::any: 2.11469
    boost::spirit::hold_any: 0.260436
    std::any: 0.187236
    void *: 0.0305599

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: