В книге Скотта Мейерса я нашел пример универсального обобщенного лямбда-выражения, которое можно использовать для измерения времени выполнения функции. (C ++ 14)
auto timeFuncInvocation =
[](auto&& func, auto&&... params) {
// get time before function invocation
const auto& start = std::chrono::high_resolution_clock::now();
// function invocation using perfect forwarding
std::forward<decltype(func)>(func)(std::forward<decltype(params)>(params)...);
// get time after function invocation
const auto& stop = std::chrono::high_resolution_clock::now();
return stop - start;
};
Проблема в том, что вы измеряете только одно выполнение, поэтому результаты могут сильно отличаться. Чтобы получить достоверный результат, следует замерить большое количество исполнений. Согласно лекции Андрея Александреску на конференции code :: dive 2015 - Writing Fast Code I:
Измеренное время: tm = t + tq + tn + to
где:
tm - измеренное (наблюдаемое) время
t - актуальное интересующее время
tq - время, добавленное шумом квантования
tn - время, добавленное различными источниками шума
to - время накладных расходов (измерение, цикл, вызов функций)
Согласно тому, что он сказал позже в лекции, вы должны принять как минимум это большое количество казней в качестве результата. Я рекомендую вам посмотреть лекцию, в которой он объясняет почему.
Также есть очень хорошая библиотека от Google - https://github.com/google/benchmark . Эта библиотека очень проста в использовании и мощна. Вы можете просмотреть некоторые лекции Чендлера Каррута на YouTube, где он использует эту библиотеку на практике. Например, CppCon 2017: Чендлер Каррут «Быстрее никуда не денешься»;
Пример использования:
#include <iostream>
#include <chrono>
#include <vector>
auto timeFuncInvocation =
[](auto&& func, auto&&... params) {
// get time before function invocation
const auto& start = high_resolution_clock::now();
// function invocation using perfect forwarding
for(auto i = 0; i < 100000/*largeNumber*/; ++i) {
std::forward<decltype(func)>(func)(std::forward<decltype(params)>(params)...);
}
// get time after function invocation
const auto& stop = high_resolution_clock::now();
return (stop - start)/100000/*largeNumber*/;
};
void f(std::vector<int>& vec) {
vec.push_back(1);
}
void f2(std::vector<int>& vec) {
vec.emplace_back(1);
}
int main()
{
std::vector<int> vec;
std::vector<int> vec2;
std::cout << timeFuncInvocation(f, vec).count() << std::endl;
std::cout << timeFuncInvocation(f2, vec2).count() << std::endl;
std::vector<int> vec3;
vec3.reserve(100000);
std::vector<int> vec4;
vec4.reserve(100000);
std::cout << timeFuncInvocation(f, vec3).count() << std::endl;
std::cout << timeFuncInvocation(f2, vec4).count() << std::endl;
return 0;
}
РЕДАКТИРОВАТЬ: Конечно, вам всегда нужно помнить, что ваш компилятор может что-то оптимизировать или нет. В таких случаях могут быть полезны такие инструменты, как perf.
clock_gettime
.. gcc определяет другие часы как:typedef system_clock steady_clock; typedef system_clock high_resolution_clock;
в Windows используйтеQueryPerformanceCounter
.