Ich habe einen Benchmark durchgeführt, bei dem eine rekursive Funktion mit einer rekursiven Lambda-Funktion unter Verwendung der std::function<>
Erfassungsmethode verglichen wurde . Mit vollständigen Optimierungen in Clang Version 4.1 lief die Lambda-Version deutlich langsamer.
#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);
}
Erzeugt Ergebnisse:
Duration: 0 // regular function
Duration: 4027 // lambda function
(Hinweis: Ich habe auch mit einer Version bestätigt, die die Eingaben von cin übernommen hat, um die Auswertung der Kompilierungszeit zu vermeiden.)
Clang erzeugt auch eine Compiler-Warnung:
main.cc:10:29: warning: variable 'sum2' is uninitialized when used within its own initialization [-Wuninitialized]
Was erwartet und sicher ist, sollte aber beachtet werden.
Es ist großartig, eine Lösung in unseren Toolbelts zu haben, aber ich denke, die Sprache wird einen besseren Weg brauchen, um diesen Fall zu behandeln, wenn die Leistung mit den aktuellen Methoden vergleichbar sein soll.
Hinweis:
Wie ein Kommentator betonte, scheint die neueste Version von VC ++ einen Weg gefunden zu haben, dies bis zur gleichen Leistung zu optimieren. Vielleicht brauchen wir doch keinen besseren Weg, um damit umzugehen (außer für syntaktischen Zucker).
Wie einige andere SO-Beiträge in den letzten Wochen dargelegt haben, kann die Leistung std::function<>
selbst die Ursache für die Verlangsamung gegenüber der direkten Aufruffunktion sein, zumindest wenn die Lambda-Erfassung zu groß ist, um in einige bibliotheksoptimierte Raumnutzungen std::function
für kleine Funktoren zu passen (Ich denke, irgendwie mögen die verschiedenen Optimierungen für kurze Zeichenfolgen?).