Dalam buku Scott Meyers saya menemukan contoh ekspresi lambda generik universal yang dapat digunakan untuk mengukur waktu eksekusi fungsi. (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;
};
Masalahnya adalah Anda hanya mengukur satu eksekusi sehingga hasilnya bisa sangat berbeda. Untuk mendapatkan hasil yang andal, Anda harus mengukur sejumlah besar eksekusi. Menurut Andrei Alexandrescu kuliah di code :: dive 2015 conference - Writing Fast Code I:
Waktu yang diukur: tm = t + tq + tn + hingga
dimana:
tm - waktu diukur (diamati)
t - waktu aktual bunga
tq - waktu ditambahkan oleh noise kuantisasi
Waktu ditambahkan oleh berbagai sumber kebisingan
ke - waktu overhead (fungsi pengukuran, perulangan, panggilan)
Menurut apa yang dia katakan nanti dalam perkuliahan, Anda harus mengambil minimal eksekusi dalam jumlah besar ini sebagai hasilnya. Saya mendorong Anda untuk melihat ceramah di mana dia menjelaskan mengapa.
Juga ada perpustakaan yang sangat bagus dari google - https://github.com/google/benchmark . Perpustakaan ini sangat mudah digunakan dan kuat. Anda dapat checkout beberapa ceramah Chandler Carruth di youtube di mana dia menggunakan perpustakaan ini dalam praktek. Misalnya CppCon 2017: Chandler Carruth “Going Nowhere Faster”;
Contoh penggunaan:
#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: Tentu saja Anda selalu perlu mengingat bahwa kompiler Anda dapat mengoptimalkan sesuatu atau tidak. Alat seperti perf dapat berguna dalam kasus seperti itu.
clock_gettime
.. gcc mendefinisikan jam lain sebagai:typedef system_clock steady_clock; typedef system_clock high_resolution_clock;
pada Windows, gunakanQueryPerformanceCounter
.