Ich höre ständig, wie schlecht Reflexion zu verwenden ist. Während ich Reflexionen im Allgemeinen vermeide und selten Situationen finde, in denen es unmöglich ist, mein Problem ohne sie zu lösen, habe ich mich gefragt ...
Haben Sie für diejenigen, die Reflexion in Anwendungen verwendet haben, Leistungstreffer gemessen und ist das wirklich so schlimm?
c#
.net
performance
reflection
Dan Herbert
quelle
quelle
Antworten:
Es ist. Aber das hängt davon ab, was Sie versuchen zu tun.
Ich verwende Reflection, um Assemblys (Plugins) dynamisch zu laden, und die Leistungsbeeinträchtigung ist kein Problem, da der Vorgang beim Starten der Anwendung ausgeführt wird.
Wenn Sie jedoch in einer Reihe verschachtelter Schleifen mit jeweils Reflexionsaufrufen reflektieren, sollten Sie Ihren Code erneut aufrufen :)
Für "ein paar Mal" -Operationen ist die Reflexion vollkommen akzeptabel und Sie werden keine Verzögerung oder Probleme damit bemerken. Es ist ein sehr leistungsfähiger Mechanismus und wird sogar von .NET verwendet, daher verstehe ich nicht, warum Sie es nicht ausprobieren sollten.
quelle
Jeff Richter zeigt in seinem Vortrag The Performance of Everyday Things , dass das Aufrufen einer Methode durch Reflexion etwa 1000-mal langsamer ist als das normale Aufrufen.
Jeffs Tipp: Wenn Sie die Methode mehrmals aufrufen müssen, verwenden Sie Reflection einmal, um sie zu finden, weisen Sie sie dann einem Delegaten zu und rufen Sie den Delegaten auf.
quelle
Die Reflexionsleistung hängt von der Implementierung ab (wiederholte Aufrufe sollten zwischengespeichert werden, z
entity.GetType().GetProperty("PropName")
. B. :) . Da der größte Teil der Reflexion, die ich täglich sehe, zum Auffüllen von Entitäten aus Datenlesern oder anderen Strukturen vom Repository-Typ verwendet wird, habe ich beschlossen, die Leistung speziell anhand der Reflexion zu bewerten, wenn sie zum Abrufen oder Festlegen von Objekteigenschaften verwendet wird.Ich habe einen Test entwickelt, der meiner Meinung nach fair ist, da er alle sich wiederholenden Aufrufe und nur den tatsächlichen SetValue- oder GetValue-Aufruf zwischenspeichert. Der gesamte Quellcode für den Leistungstest befindet sich in bitbucket unter: https://bitbucket.org/grenade/accessortest . Kontrolle ist willkommen und erwünscht.
Ich bin zu dem Schluss gekommen, dass das Entfernen von Reflexionen in einer Datenzugriffsschicht, die weniger als 100.000 Zeilen zu einem Zeitpunkt zurückgibt, an dem die Reflexionsimplementierung gut durchgeführt wird, nicht praktikabel ist und keine merklichen Leistungsverbesserungen bietet.
Die obige Grafik zeigt die Ausgabe meines kleinen Benchmarks und zeigt, dass Mechanismen, die die Reflexion übertreffen, dies erst nach der 100.000-Zyklen-Marke merklich tun. Die meisten DALs geben jeweils nur einige hundert oder vielleicht Tausende von Zeilen zurück, und auf diesen Ebenen funktioniert die Reflexion einwandfrei.
quelle
Wenn Sie nicht in einer Schleife sind, machen Sie sich darüber keine Sorgen.
quelle
Meine relevanteste Erfahrung war das Schreiben von Code, um zwei beliebige Datenentitäten desselben Typs in einem großen Objektmodell in Bezug auf die Eigenschaften zu vergleichen. Habe es zum Laufen gebracht, es ausprobiert, bin offensichtlich wie ein Hund gelaufen.
Ich war verzweifelt und erkannte dann über Nacht, dass ich ohne Änderung der Logik denselben Algorithmus verwenden konnte, um automatisch Methoden für den Vergleich zu generieren, aber statisch auf die Eigenschaften zuzugreifen. Es dauerte überhaupt keine Zeit, den Code für diesen Zweck anzupassen, und ich hatte die Möglichkeit, Entitäten mit statischem Code zu vergleichen, der auf Knopfdruck aktualisiert werden konnte, wenn sich das Objektmodell änderte.
Mein Punkt ist: In Gesprächen mit Kollegen, seit ich mehrmals darauf hingewiesen habe, dass ihre Verwendung von Reflektion darin bestehen könnte, Code automatisch zu generieren, um Laufzeitoperationen zu kompilieren, anstatt sie auszuführen, und dies ist oft eine Überlegung wert.
quelle
Nicht massiv. Ich hatte noch nie ein Problem damit in der Desktop-Entwicklung, es sei denn, Sie verwenden es, wie Martin feststellt, an einem dummen Ort. Ich habe gehört, dass viele Leute völlig irrationale Befürchtungen hinsichtlich der Leistung bei der Desktop-Entwicklung haben.
Im Compact Framework (in dem ich normalerweise bin) ist es jedoch ziemlich anathema und sollte in den meisten Fällen wie die Pest vermieden werden. Ich kann immer noch selten damit durchkommen, aber ich muss sehr vorsichtig mit der Anwendung sein, die viel weniger Spaß macht. :((
quelle
Es ist schon schlimm genug, dass Sie sich Sorgen machen müssen, selbst wenn die .NET-Bibliotheken intern über leistungskritischen Code nachdenken.
Das folgende Beispiel ist veraltet - zu der Zeit (2008) wahr, aber in neueren CLR-Versionen längst behoben. Reflexion im Allgemeinen ist jedoch immer noch etwas kostspielig!
Beispiel: Sie sollten niemals ein Mitglied verwenden, das als "Objekt" in einer Lock (C #) / SyncLock (VB.NET) -Anweisung in Hochleistungscode deklariert ist. Warum? Da die CLR einen Werttyp nicht sperren kann, muss sie zur Laufzeit eine Reflexionstypprüfung durchführen, um festzustellen, ob Ihr Objekt tatsächlich ein Werttyp anstelle eines Referenztyps ist.
quelle
Wie bei allen Dingen in der Programmierung müssen Sie die Leistungskosten mit den erzielten Vorteilen in Einklang bringen. Reflexion ist ein unschätzbares Werkzeug, wenn sie mit Sorgfalt verwendet wird. Ich habe eine O / R-Zuordnungsbibliothek in C # erstellt, in der die Bindungen mithilfe von Reflektion erstellt wurden. Das hat fantastisch gut funktioniert. Der größte Teil des Reflexionscodes wurde nur einmal ausgeführt, sodass jeder Leistungseinbruch recht gering war, aber die Vorteile waren groß. Wenn ich einen neuen Fandangled-Sortieralgorithmus schreiben würde, würde ich wahrscheinlich keine Reflexion verwenden, da er wahrscheinlich schlecht skaliert.
Ich schätze, dass ich Ihre Frage hier nicht genau beantwortet habe. Mein Punkt ist, dass es nicht wirklich wichtig ist. Verwenden Sie gegebenenfalls Reflexion. Es ist nur eine weitere Sprachfunktion, die Sie lernen müssen, wie und wann Sie sie verwenden sollen.
quelle
Reflexion kann spürbare Auswirkungen auf die Leistung haben, wenn Sie sie für die häufige Objekterstellung verwenden. Ich habe eine Anwendung entwickelt, die auf dem Composite UI Application Block basiert und stark auf Reflexion beruht. Es gab einen merklichen Leistungsabfall im Zusammenhang mit der Objekterstellung durch Reflexion.
In den meisten Fällen gibt es jedoch keine Probleme mit der Verwendung von Reflexionen. Wenn Sie nur eine Baugruppe inspizieren müssen, würde ich Mono.Cecil empfehlen, das sehr leicht und schnell ist
quelle
Die Reflexion ist kostspielig, da die Laufzeit viele Überprüfungen durchführen muss, wenn Sie eine Methode anfordern, die einer Liste von Parametern entspricht. Irgendwo tief im Inneren existiert Code, der alle Methoden für einen Typ durchläuft, seine Sichtbarkeit überprüft, den Rückgabetyp überprüft und auch den Typ jedes einzelnen Parameters überprüft. All dieses Zeug kostet Zeit.
Wenn Sie diese Methode intern ausführen, gibt es Code, der beispielsweise überprüft, ob Sie eine kompatible Liste von Parametern übergeben haben, bevor Sie die eigentliche Zielmethode ausführen.
Wenn möglich, wird immer empfohlen, das Methodenhandle zwischenzuspeichern, wenn es in Zukunft kontinuierlich wiederverwendet werden soll. Wie bei allen guten Programmiertipps ist es oft sinnvoll, sich nicht zu wiederholen. In diesem Fall wäre es verschwenderisch, die Methode mit bestimmten Parametern kontinuierlich nachzuschlagen und sie dann jedes Mal auszuführen.
Stöbern Sie in der Quelle und schauen Sie sich an, was getan wird.
quelle
Wie bei allem geht es darum, die Situation einzuschätzen. In DotNetNuke gibt es eine ziemlich zentrale Komponente namens
FillObject
, die Reflexion verwendet, um Objekte aus Datenzeilen zu füllen.Dies ist ein recht häufiges Szenario, und es gibt einen Artikel über MSDN, Verwenden der Reflexion zum Binden von Geschäftsobjekten an ASP.NET-Formularsteuerelemente , der die Leistungsprobleme behandelt.
Abgesehen von der Leistung ist eine Sache, die ich an der Verwendung von Reflection in diesem bestimmten Szenario nicht mag, dass sie dazu neigt, die Fähigkeit zu verringern, den Code auf einen Blick zu verstehen, was für mich die Mühe nicht wert zu sein scheint, wenn man bedenkt, dass man auch die Kompilierung verliert Zeitsicherheit im Gegensatz zu stark typisierten Datasets oder ähnlichem wie LINQ to SQL .
quelle
Reflexion verlangsamt die Leistung Ihrer App nicht drastisch. Möglicherweise können Sie bestimmte Dinge schneller erledigen, indem Sie keine Reflexion verwenden. Wenn jedoch Reflexion der einfachste Weg ist, um bestimmte Funktionen zu erreichen, verwenden Sie sie. Sie können Ihren Code jederzeit außerhalb von Reflection umgestalten, wenn dies zu einem Perf-Problem wird.
quelle
Ich denke, Sie werden feststellen, dass die Antwort lautet, es kommt darauf an. Es ist keine große Sache, wenn Sie es in Ihre Aufgabenlistenanwendung aufnehmen möchten. Es ist eine große Sache, wenn Sie es in die Persistenzbibliothek von Facebook aufnehmen möchten.
quelle