У книзі Скотта Майєрса я знайшов приклад універсального загального вираження лямбда, який можна використовувати для вимірювання часу виконання функції. (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 :: дайв 2015 - Написання швидкого коду I:
Виміряний час: tm = t + tq + tn + to
де:
tm - вимірюваний (спостережуваний) час
t - фактичний час, що цікавить
tq - час, доданий шумом квантування
tn - час, доданий різними джерелами шуму
до - накладний час (функції вимірювання, циклу, виклику)
Відповідно до того, що він сказав пізніше на лекції, ви повинні взяти як мінімум цю велику кількість страт як результат. Я закликаю вас подивитися на лекцію, в якій він пояснює, чому.
Також є дуже хороша бібліотека від Google - https://github.com/google/benchmark . Ця бібліотека дуже проста у використанні та потужна. Ви можете прочитати кілька лекцій Чендлера Каррута на youtube, де він використовує цю бібліотеку на практиці. Наприклад, CppCon 2017: Carruth Chandler "Швидше нікуди";
Приклад використання:
#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;
}
EDIT: Звичайно, вам завжди потрібно пам’ятати, що ваш компілятор може щось оптимізувати чи ні. Такі засоби, як перф, можуть бути корисними в таких випадках.
clock_gettime
.. gcc визначає інші годинники як:typedef system_clock steady_clock; typedef system_clock high_resolution_clock;
у Windows, використовуйтеQueryPerformanceCounter
.