J'ai couru un indice de référence de la comparaison d'une fonction récursive vs récursive une fonction lambda à l'aide de la std::function<> méthode de capture. Avec plein optimisations activées sur clang la version 4.1, le lambda version couru beaucoup plus lents.
#include <iostream>
#include <functional>
#include <chrono>
uint64_t sum1(int n) {
return (n <= 1) ? 1 : n + sum1(n - 1);
}
std::function<uint64_t(int)> sum2 = [&] (int n) {
return (n <= 1) ? 1 : n + sum2(n - 1);
};
auto const ITERATIONS = 10000;
auto const DEPTH = 100000;
template <class Func, class Input>
void benchmark(Func&& func, Input&& input) {
auto t1 = std::chrono::high_resolution_clock::now();
for (auto i = 0; i != ITERATIONS; ++i) {
func(input);
}
auto t2 = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count();
std::cout << "Duration: " << duration << std::endl;
}
int main() {
benchmark(sum1, DEPTH);
benchmark(sum2, DEPTH);
}
Produit des résultats:
Duration: 0 // regular function
Duration: 4027 // lambda function
(Note: j'ai aussi confirmé avec une version qui a pris les entrées de cin, de façon à éliminer les temps de compilation d'évaluation)
Clang produit également un avertissement du compilateur:
main.cc:10:29: warning: variable 'sum2' is uninitialized when used within its own initialization [-Wuninitialized]
Ce qui est prévu, et en toute sécurité, mais doivent être notées.
C'est génial d'avoir une solution dans notre toolbelts, mais je pense que la langue aurez besoin d'une meilleure façon de gérer ce cas, si la performance est comparable aux méthodes actuelles.
Note:
Comme un intervenant l'a souligné, il semble que la dernière version de VC++ a trouvé un moyen d'optimiser ce au point de performance égale. Peut-être que nous n'avons pas besoin d'une meilleure façon de gérer cela, après tout (sauf pour le sucre syntaxique).
Aussi, comme certains autres, AFIN de postes ont indiqué ces dernières semaines, la performance de std::function<> lui-même peut être la cause de ralentissement vs appeler directement la fonction, au moins lorsque le lambda de capture est trop grand pour tenir dans une bibliothèque-espace optimisé std::function utilise pour les petits-foncteurs (je pense un peu comme les différents courte chaîne optimisations?).