I recently noticed that I was having a performance hit because I was declaring a default constructor like:
Foo() = default;
instead of
Foo() {}
(Just FYI, I needed to explicitly declare it because I also had a variadic constructor that would otherwise override the default constructor)
This seemed strange to me because I thought that these two lines of code are identical (Well, so long as a default constructor is possible. If the default constructor isn't possible, the second line of code would produce an error and the first would implicitly delete the default constructor. 'Not my situation!).
Okay, so I made a little tester and the results vary quite a lot depending on the compiler, but with certain settings I get consistent results that one is faster over the other:
#include <chrono>
template <typename T>
double TimeDefaultConstructor (int n_iterations)
{
auto start_time = std::chrono::system_clock::now();
for (int i = 0; i < n_iterations; ++i)
T t;
auto end_time = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end_time - start_time;
return elapsed_seconds.count();
}
template <typename T, typename S>
double CompareDefaultConstructors (int n_comparisons, int n_iterations)
{
int n_comparisons_with_T_faster = 0;
for (int i = 0; i < n_comparisons; ++i)
{
double time_for_T = TimeDefaultConstructor<T>(n_iterations);
double time_for_S = TimeDefaultConstructor<S>(n_iterations);
if (time_for_T < time_for_S)
++n_comparisons_with_T_faster;
}
return (double) n_comparisons_with_T_faster / n_comparisons;
}
#include <vector>
template <typename T>
struct Foo
{
std::vector<T> data_;
Foo() = default;
};
template <typename T>
struct Bar
{
std::vector<T> data_;
Bar() {};
};
#include <iostream>
int main ()
{
int n_comparisons = 10000;
int n_iterations = 10000;
typedef int T;
double result = CompareDefaultConstructors<Foo<T>,Bar<T>> (n_comparisons, n_iterations);
std::cout << "With " << n_comparisons << " comparisons of " << n_iterations
<< " iterations of the default constructor, Foo<" << typeid(T).name() << "> was faster than Bar<" << typeid(T).name() << "> "
<< result*100 << "% of the time" << std::endl;
std::cout << "swapping orientation:" << std::endl;
result = CompareDefaultConstructors<Bar<T>,Foo<T>> (n_comparisons, n_iterations);
std::cout << "With " << n_comparisons << " comparisons of " << n_iterations
<< " iterations of the default constructor, Bar<" << typeid(T).name() << "> was faster than Foo<" << typeid(T).name() << "> "
<< result*100 << "% of the time" << std::endl;
return 0;
}
Using the above program with g++ -std=c++11 I consistently get output similar to:
With 10000 comparisons of 10000 iterations of the default constructor, Foo was faster than Bar 4.69% of the time swapping orientation: With 10000 comparisons of 10000 iterations of the default constructor, Bar was faster than Foo 96.23% of the time
Changing the compiler settings seems to change the result, sometimes flipping it entirely. But what I can't understand is why it matters at all?
system_clockto time things is not a good idea.