Die Leistung der Aufruf Delegierten vs-Methoden
Folgenden diese Frage - Pass-Methode als Parameter mit C# und einige meiner persönlichen Erfahrung ich würde gerne wissen, ein wenig mehr über die Leistung der Aufruf einer delegate vs nur den Aufruf einer Methode in C#.
Obwohl die Delegierten sind äußerst bequem, ich hatte eine app, die hat viele Rückrufe per Delegierten und, wenn wir schrieben das verwenden von callback-Schnittstellen haben wir eine Größenordnung, die Verbesserung der Geschwindigkeit. Dies war mit .NET 2.0, so dass ich nicht sicher bin, wie sich die Dinge verändert haben mit 3 und 4.
Wie werden Anrufe an Stellvertretungen intern im compiler/CLR und wie wirkt sich dies auf die Leistung der Methode Aufrufe?
BEARBEITEN - um Zu verdeutlichen, was ich meine, von den Delegierten vs-callback-interfaces.
Für asynchrone Aufrufe meiner Klasse könnte eine OnComplete-event und der damit verbundenen Delegierten, die der Anrufer konnte abonnieren.
Alternativ könnte ich erstellen Sie eine ICallback-Schnittstelle mit der OnComplete-Methode, die der Anrufer implementiert und dann registriert sich bei der Klasse, rufen Sie dann diese Methode auf die Fertigstellung (d.h. die Art und Weise Java-Griffe diese Dinge).
Siehe stackoverflow.com/questions/1269452/... und stackoverflow.com/questions/304770/... - mögliche Duplikate?
Delegierte sind erforderlich, wenn Sie die Ausführung separater threads und die Notwendigkeit einer Schnittstelle mit dem UI-thread.. so müssen Sie verfeinern Ihre Frage mehr zu sein, mehr lokal und weniger generisch.
InformationsquelleAutor Paolo | 2010-01-17
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich habe nicht gesehen, dass die Wirkung - ich habe jedenfalls noch nie festgestellt, dass es ein Engpass.
Hier ist eine sehr grobe-and-ready-benchmark, die zeigt (auf meinem Rechner jedenfalls) die Delegierten tatsächlich schneller als Schnittstellen:
Ergebnisse (.NET 3.5; .NET 4.0b2 ist ungefähr die gleiche):
Nun ich habe keinen bestimmten glauben, dass das bedeutet, dass die Delegierten sind wirklich schneller als Schnittstellen... aber es macht mich ziemlich überzeugt, dass Sie nicht eine Größenordnung langsamer. Darüber hinaus ist dies das tun fast nichts innerhalb der Delegierte/interface-Methode. Offensichtlich wurde der Aufruf Kosten gehen, um weniger und weniger Unterschied als man mehr und mehr Arbeit pro Anruf.
Eine Sache, vorsichtig zu sein, ist, dass Sie nicht die Schaffung eines neuen Delegierten mehrmals, wo Sie würde nur mit einem einzigen interface-Instanz. Diese könnte ein Problem verursachen, wie es wäre, zu provozieren, garbage collection, etc. Wenn Sie eine Instanz-Methode als Delegierter innerhalb einer Schleife, finden Sie es effizienter, erklären die delegate-variable außerhalb der Schleife, erstellen Sie eine einzelne Instanz delegieren und wiederverwenden. Zum Beispiel:
ist effizienter als:
War das problem, das Sie sahen?
Würde sich dies ändern, wenn Sie sich in einer Veranstaltung mit den Delegierten?
Danke Jon, ich glaube nicht, es war ein überschuss an Objekten/Müll-Sammlung, sondern Ihre benchmark-sauber zeigt, dass die Delegierten sind mindestens so schnell, so unabhängig von der ursprünglichen Ursache werde ich patch mein internes wissen mit diesen Ergebnissen 😉
- Was ist Leistung ? Action/Func umgesetzt werden, so die Delegierten. Die Delegierten sind implementiert in der IL-compiler-generierten Klassen mit einer Invoke () - Methode. Aufruf von foo (), wenn foo ist ein Delegat, der wirklich kompiliert unten der Aufruf von foo.Invoke(), die wiederum ruft die Ziel-code. Wenn foo ist eine tatsächliche Methode, die anstelle eines Delegaten ruft foo() ruft direkt an den Ziel-code ohne Invoke () - intermediate. Finden Sie ILDASM für den Nachweis. stackoverflow.com/a/8449833/206730
Wenn Sie eine Schnittstelle oder eine virtuelle Methode als gut, das stellt eine zusätzliche Ebene der Dereferenzierung als gut. Ja, Sie können sich etwas bessere performance, wenn Sie nur auf eine nicht-virtuelle Methode direkt, aber es ist selten tatsächlich signifikant in meiner Erfahrung.
InformationsquelleAutor Jon Skeet
Da CLR-v 2, die Kosten der Delegat Aufruf ist sehr nah an der virtuellen Methodenaufruf, das ist für die interface-Methoden.
Sehen Joel Pobar's blog.
InformationsquelleAutor Pete Montgomery
Ich finde es völlig unplausibel, dass ein Delegat ist wesentlich schneller oder langsamer als eine virtuelle Methode. Wenn etwas die Delegierten werden sollte vernachlässigbar schneller. Auf einer niedrigeren Ebene, die Delegierten sind in der Regel implementiert, so etwas wie (mit C-notation, aber bitte verzeihen Sie jede kleine syntax-Fehler, da dies nur eine illustration):
Den Aufruf einer delegate-funktioniert so etwas wie:
Einer Klasse, übersetzt von C, wäre so etwas wie:
Nennen Sie eine vritual Funktion, Sie würde das folgende tun:
Sie sind im Grunde die gleichen, außer, dass bei der Verwendung von virtuellen Funktionen, die Sie gehen Sie durch eine zusätzliche Schicht der Dereferenzierung, um die Funktionszeiger. Jedoch, diese zusätzliche indirection layer ist oft kostenlos, da moderne CPU Zweig Prädiktoren zu erraten, die Adresse der Funktion, die Zeiger und spekulativ ausführen Ihr Ziel nicht parallel sucht die Adresse der Funktion. Ich habe festgestellt, (wenn auch in D, nicht C#), die virtuelle Funktionsaufrufe in einer engen Schleife sind nicht langsamer als non-inlined direkte Anrufe, vorausgesetzt, dass für einen bestimmten Lauf der Schleife, werden Sie immer auflösen in die gleiche Reale Funktion.
Wenn es nur mehr wirklich, die technische Fragen wie diese auf, SO, die zeigen, wie die zugrunde liegenden Implementierungen erreicht wurden, anstatt zu erwarten askers zu Vertrauen, blinden glauben, dass "es so ist".
InformationsquelleAutor dsimcha
Habe ich einige tests (in .Net 3.5... später werde ich schauen zu Hause mit .Net 4).
Die Tatsache ist:
Immer ein Objekt, eine Schnittstelle, und dann die Ausführung der Methode ist schneller, als sich ein Delegierter aus einer Methode, die dann den Aufruf des Delegaten.
Unter Berücksichtigung der Variablen ist bereits in den richtigen Typ (interface oder delegieren) und einfach aufrufen, es macht die Stellvertretung gewinnen.
Aus irgendeinem Grund, immer ein Delegat, der über eine interface-Methode (vielleicht über irgendeine virtuelle Methode) ist VIEL langsamer.
Und, wenn man bedenkt es gibt Fälle, wenn wir einfach nicht pre-store-die Stellvertretung (wie in Depeschen, zum Beispiel), das kann begründen, warum interfaces sind schneller.
Hier sind die Ergebnisse:
Um wirkliche Ergebnisse, kompilieren Sie diese im Release-Modus, und führen Sie es außerhalb der Visual Studio.
Wie Sie sehen können, ist der direkte Anrufe sind wirklich schnell.
Die Speicherung der Schnittstelle oder eine Stellvertretung vor, und dann nur aufrufen es ist wirklich schnell.
Aber nachdem man ein Delegat ist langsamer, als wenn man eine Schnittstelle.
Nachdem man ein Delegat, der über eine interface-Methode (oder einer virtuellen Methode, nicht sicher) ist wirklich sehr langsam (Vergleich der 5 Sekunden, ein Objekt, eine Schnittstelle, die fast 4 Minuten das gleiche zu tun um die Aktion).
Den code, der generiert diese Ergebnisse ist hier:
Schöne benchmarks, danke. Ich habe versucht, eine Reihe von Variationen und festgestellt, dass: der direkte Anrufe sind immer die schnellsten; statische direkte Anrufe sind nicht schneller als Instanz-member direkte Anrufe; .NET 4 ist langsamer für direkte Anrufe, obwohl schneller in einigen anderen Fällen; kompilieren mit "optimieren /+" hilft, aber "/debug " -" und "/geprüft-" don ' T einen Unterschied machen; "/Plattform:x64" hat keinen Einfluss auf timings, aber "/Plattform:x86" ist (schneller in ein paar Fällen langsamer in den meisten); Trennung von tests in Ihre eigenen Methoden, die keinen Unterschied macht, setzen Runnable in einer separaten assembly, macht keinen Unterschied.
InformationsquelleAutor Paulo Zemek
Was ist mit der Tatsache, dass die Delegierten sind Container? Nicht die multicast-Fähigkeit hinzufügen overhead? Während wir auf das Thema, was wäre, wenn wir schieben diese container Aspekt ein wenig weiter? Nichts verbietet uns, falls d ein Delegierter, von der Ausführung d += d; oder vom Bau einer beliebig komplexen gerichteten Graphen (Kontext-Zeiger, Methode, pointer) Paare. Wo finde ich die Dokumentation, die beschreibt, wie dieser graph Durchlaufen wird, wenn der Delegat aufgerufen wird?
Beachten Sie, dass der Ansatz, den ich gerade beschrieb, ist das nicht AFAIK, wie MulticastDelegates umgesetzt werden, aber es wäre ein Mechanismus für die Optimierung am häufigsten (genau ein Ziel -) Fall.
InformationsquelleAutor Dorian Yeager