Click to See Complete Forum and Search --> : Why is this slow...


zennehoy
April 1st, 2008, 08:59 AM
Hello all,
I'm trying to write a simple and efficient logger class using template metaprogramming, but am failing miserably (at least on the efficiency part). I thought that an empty inline function would be optimized away, but apparantly it isn't; or I'm doing something else wrong. Here's the simplified code:

#include <windows.h>
#include <iostream>
#include <string>

template <bool T>
class logger { };

template <typename T>
inline logger<true> const &operator<<(logger<true> const &lg, T const &t) {
std::cout << t;
return lg;
}
inline logger<true> const &operator<<(logger<true> const &lg, std::basic_ostream<char, std::char_traits<char> >&(*t)(std::basic_ostream<char, std::char_traits<char> >&)) {
std::cout << t;
return lg;
}

template <typename T>
inline logger<false> const &operator<<(logger<false> const &lg, T const &t) {
return lg;
}
inline logger<false> const &operator<<(logger<false> const &lg, std::basic_ostream<char, std::char_traits<char> >&(*t)(std::basic_ostream<char, std::char_traits<char> >&)) {
return lg;
}

template <bool T>
inline logger<T> &log() { static logger<T> lgr; return lgr; }

int main() {
for(int j=0; j<10; ++j) {
unsigned int i = GetTickCount();
for(int i=0; i<100000000; ++i) {
// With this line takes 1500 ms, without takes 250 ms
log<false>() << "string" << 42 << std::endl;
}

i = GetTickCount() - i;

std::cout << i << std::endl;
}

return 0;
}

I would expect that the overloaded stream operator be compiled away, since it does nothing. Isn't that exactly what template metaprogramming is all about? Or am I doing something fundamentally wrong? I get practically identical poor results with both MSVC and GCC.
Thanks in advance for the help!
Zen

pm_kirkham
April 1st, 2008, 10:32 AM
Whether a function which 'does nothing' is optimised away by the compiler is nothing to do with template metaprogramming. Template metaprogramming merely lets you control which function is called at compile time, it's up to the compiler's optimisation routines to eliminate code with no effect if the function selected by the template is empty.

Both g++ 3.4 wingw special and MSVC2005 show signs of optimising the function call (mostly) away when using -O3 or Release:

g++ -O0:
1593
1406
...

g++ -O3:
234
109
...

VS2005 Debug:
10454
10453
...

VS2005 Release:
0
0
...

> Or am I doing something fundamentally wrong?
Don't run benchmarks on unoptimised builds.

zennehoy
April 2nd, 2008, 02:38 AM
Alright, I feel silly :) I really would have expected a Visual Studio Release Build to enable optimizations by default... apparently not.
Thanks!
Zen

S_M_A
April 2nd, 2008, 03:10 AM
Eh, release build in VS is set to /O2 as default.