Optimierung von Func.Invoke () aus der Ausdrucksbaumstruktur generiert

8

Ich arbeite an einer Automatisierung für die dynamische Instanziierung von Klassen.

Ich entschied mich, einen Ausdrucksbaum zu schreiben, der ein Func erzeugen würde, das meine Klasse für mich instanziieren könnte. Allerdings bemerke ich eine 3x langsamere Leistung von Func im Gegensatz zu new .

Was ich über Ausdrucksbäume und Aufruffunktionen weiß, sollte der Leistungsunterschied fast nicht existieren (vielleicht 20-30%, aber nicht annähernd dreimal langsamer)

Zunächst einmal, hier ist der Ausdruck, den ich erstelle

%Vor%

Ich fahre dann fort, es so zu kompilieren (ich mache das nur einmal)

%Vor%

Und dann rufe ich meinen Func so an

%Vor%

Wenn ich diesen letzten Teil in eine Schleife lege und vergleiche es mit etwas wie

%Vor%

Ich habe ein paar Tests gemacht, die Leistung in beiden verglichen, und das ist es, womit ich endete:

%Vor%

Wie Sie sehen können, ist mein Func.Invoke() ungefähr 2,5 - 3 mal langsamer als das Instanziieren mit new . Hat jemand irgendwelche Tipps, wie ich das verbessern könnte? (Es macht mir nichts aus, reine Reflexion zu verwenden, wenn ich bessere Leistung erziele)

* Für alle, die das hier testen wollen, ist ein Pastebin meines Setups: Ссылка

    
Hentov 04.01.2018, 16:30
quelle

2 Antworten

2

Nachdem ich alle Beiträge in den Kommentaren durchgelesen habe, kam ich auf diese Idee: Wenn Sie ein DynamicMethod anstelle eines Ausdrucksbaums erstellen und es dem Modul des aktuell ausgeführten Codes logisch zuweisen, sollten Sie dies nicht tun bekomme diesen Overhead.

Ich denke (oder hoffe zumindest), dass Sie nach Verbesserungsoptionen für die allgemeine Idee gesucht haben, nicht speziell für die Ausdrucksbaum-basierte Version, also poste ich dies als Verbesserungsoption:)

Also habe ich dieses Stück Code ausprobiert:

%Vor%

Und auf meinem Rechner wurden Delegaten erstellt, die maximal 1,8-mal langsamer als der handgeschriebene Code ohne Angabe des Attributs ausgeführt werden. Nicht 1.5, aber zumindest muss ich meinem Code kein assemblyweites Attribut hinzufügen, das ich nicht vollständig verstehe:)

Wenn Sie den letzten Parameter des DynamicMethod -Konstruktors weglassen, erhalten Sie immer noch die noch langsameren Ergebnisse für den generierten Code.

BEARBEITEN

Ich bin auf diesen Blogpost gestoßen, der die gleiche Frage stellt und die gleiche Lösung bietet:

Ссылка

    
Akos Nagy 04.01.2018 18:07
quelle
0

Lass mich etwas anderes ausprobieren. Die Sache, die Sie tun könnten, ist currying:

%Vor%

Dann könnte derselbe Curry-Ansatz angewendet werden, um sowohl die Standard / dynamische Implementierung beider Funktionen bereitzustellen. Ein typischer typeCreator wäre etwas ähnlich wie Activator.Create(...) . Abhängig von Ihrer Logik sind möglicherweise mehr Funktionen erforderlich. Zum Beispiel: Func<object[]> constructorArgumentsSupplier . Gleiches gilt für die Zuweisung eines bestimmten Werts zu einer bestimmten Eigenschaft: eine gute alte Reflexion: genau wie WPF.

Aber die meisten von ihnen 1) könnten nur einmal für einen bestimmten Typ erstellt und für die weitere Verwendung zwischengespeichert werden; 2) vorkompiliert anstatt auf Ausdrücke angewiesen zu sein, was eine Art von Schmerz ist.

    
Sereja Bogolubov 04.01.2018 19:19
quelle