Extension of Charles's answer .
The problem is that your loop does more than just testing the virtual call itself (memory allocation probably overshadows the overhead of the virtual call anyway), so its suggestion is to change the code to test only the virtual call.
Here, the reference function is a template, because a template can be embedded, while calling through function pointers is unlikely to be.
template <typename Type> double benchmark(Type const& t, size_t iterations) { timeval a, b; gettimeofday(&a, 0); for (;iterations > 0; --iterations) { t.getArea(); } gettimeofday(&b, 0); return (b.tv_sec * (unsigned int)1e6 + b.tv_usec) - (a.tv_sec * (unsigned int)1e6 + a.tv_usec); }
Classes:
struct Regular { Regular(size_t w, size_t h): _width(w), _height(h) {} size_t getArea() const; size_t _width; size_t _height; };
And measurement:
int main(int argc, char* argv[]) { if (argc != 2) { std::cerr << "Usage: %prog iterations\n"; return 1; } Regular regular(3, 7); std::auto_ptr<Base> derived = generateDerived(); double regTime = benchmark<Regular>(regular, atoi(argv[1])); double derTime = benchmark<Base>(*derived, atoi(argv[1])); std::cout << "Regular: " << regTime << "\nDerived: " << derTime << "\n"; return 0; }
Note. This checks the virtual call overhead compared to a regular function. The functionality is different (because in the second case you do not dispatch at runtime), but in this case the worst case overhead.
EDIT
The launch results (gcc.3.4.2, -O2, Quadcore SLES10 server) note: with function definitions in another translation unit, to prevent embedding
> ./test 5000000 Regular: 17041 Derived: 17194
Not very convincing.
Matthieu M.
source share