Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Performance: template vs boost.any

I was wondering if using boost.any (Without RTTI) classes anywhere templates can be used will slow down the program. Since boost any is actually a wrapper around a template class, one could say that with the modern compiler-optimalisations it will produce the same effect, am I right?

tpl_vs_any.hpp

#include <iostream>
#include <vector>

using namespace std;

template<class T> class tpl
{
    T content;
public:
    tpl(const T& value) : content(value) {}
    operator T() const
    {
        return content;
    }
};

class any
{
public:

    any() : content(0) {}

    any(const any& other) : content(other.content -> clone()) {}

    template<class T> any(const T& value) : content(new holder<T>(value))
    {
    }

    ~any() 
    {
        delete content;
    }

    class placeholder
    {
    public:
        placeholder() {}
        virtual placeholder* clone() const = 0;
    };

    template<class T> class holder : public placeholder
    {
    public:
        T content;

        holder(const T& value) : content(value) {}
        ~holder() {}

        placeholder* clone() const
        {
            return new holder<T>(content);
        }
    };

    template<class T> operator T () const
    {
        return dynamic_cast<holder<T>*>(content)->content;
    }

    placeholder* content;
};

template<class T> void test()
{
    for (int i = 0; i < 10000; ++i)
    {
        vector<T> a;
        a.push_back(23.23);
        a.push_back(3.14);

        double x = (double)a[0];
    }
}

So would it be correct to say that:

test<any>();

Is exactly as fast as:

test<tpl<double>>();

Assuming that you know, just like the compiler does at the second example, that boost::any is only used as double in this situation? (No RTTI for the any class).

I'm more wondering about the arguments for and against this thesis.

Also, are there specific situations where there is difference between those methods?

Edit: Performance test 2:

  • Example 1: 1,966.57 ms
  • Example 2: 1,320.37 ms

It seems like there is a relativly large difference.

Edit 2: Since it was not fair to compare the primary data type double against the class any I've made a new test:

#include "tpl_vs_any.hpp"

int main()
{
    test<any>();
    return 0;
}

Speed: 1,794.54 ms

#include "tpl_vs_any.hpp"

int main()
{
    test<tpl<double>>();
    return 0;
}

Speed: 1,715.57 ms

Tested it multiple times, pretty much the same benchmarks.

like image 221
Tim Avatar asked Oct 06 '22 15:10

Tim


2 Answers

So would it be correct to say that:

...

Is exactly as fast as:

...

Assuming that you know, just like the compiler does at the second example, that boost::any is only used as double in this situation?

No. Current compilers do nowhere near that kind of level of introspection. boost::any will be slower.

Of course, you could just run the code and find out for yourself.

like image 162
Peter Alexander Avatar answered Oct 10 '22 02:10

Peter Alexander


boost::any internally holds a pointer to an object, which it allocates with new. One of the things that makes std::vector significantly faster than, say, std::list is that vector keeps all of its objects in a contiguous storage in a single allocation, which aside from the obvious reduction in memory allocation overhead, is also a lot more cache-friendly.

There's also the detail of adding RTTI to the allocation, which is generally trivial overhead, but in the case of really small types like double significantly increases the storage overhead.

boost::any is not part of the standard; it's a specific implementation of a specific template. So you might as well just benchmark it; there aren't a bunch of other competing "standard implementations".

like image 39
rici Avatar answered Oct 10 '22 03:10

rici