Dans le livre de Scott Meyers, j'ai trouvé un exemple d'expression lambda générique universelle qui peut être utilisée pour mesurer le temps d'exécution d'une fonction. (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;
};
Le problème est que vous ne mesurez qu'une seule exécution, les résultats peuvent donc être très différents. Pour obtenir un résultat fiable, vous devez mesurer un grand nombre d'exécutions. D'après la conférence d'Andrei Alexandrescu à la conférence code :: dive 2015 - Writing Fast Code I:
Temps mesuré: tm = t + tq + tn + to
où:
tm - temps mesuré (observé)
t - le temps réel d'intérêt
tq - temps ajouté par le bruit de quantification
tn - temps ajouté par diverses sources de bruit
to - temps de surcharge (mesure, bouclage, fonctions d'appel)
D'après ce qu'il a dit plus tard dans la conférence, vous devriez prendre un minimum de ce grand nombre d'exécutions comme résultat. Je vous encourage à regarder la conférence dans laquelle il explique pourquoi.
Il existe également une très bonne bibliothèque de google - https://github.com/google/benchmark . Cette bibliothèque est très simple à utiliser et puissante. Vous pouvez consulter quelques conférences de Chandler Carruth sur youtube où il utilise cette bibliothèque dans la pratique. Par exemple CppCon 2017: Chandler Carruth «Going Nowhere Faster»;
Exemple d'utilisation:
#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: Bien sûr, vous devez toujours vous rappeler que votre compilateur peut optimiser quelque chose ou non. Des outils comme perf peuvent être utiles dans de tels cas.
clock_gettime
.. gcc définit les autres horloges comme suit:typedef system_clock steady_clock; typedef system_clock high_resolution_clock;
sous Windows, utilisezQueryPerformanceCounter
.