Meine Frage bezieht sich auf die Leistungsmerkmale statischer Methoden gegenüber Instanzmethoden und deren Skalierbarkeit. Angenommen, für dieses Szenario befinden sich alle Klassendefinitionen in einer einzelnen Assembly und es sind mehrere diskrete Zeigertypen erforderlich.
Erwägen:
public sealed class InstanceClass
{
public int DoOperation1(string input)
{
// Some operation.
}
public int DoOperation2(string input)
{
// Some operation.
}
// … more instance methods.
}
public static class StaticClass
{
public static int DoOperation1(string input)
{
// Some operation.
}
public static int DoOperation2(string input)
{
// Some operation.
}
// … more static methods.
}
Die obigen Klassen repräsentieren ein Hilfsstilmuster.
In einer Instanzklasse dauert es einen Moment, bis die Instanzmethode aufgelöst ist, im Gegensatz zu StaticClass.
Meine Fragen sind:
Wenn es nicht darum geht, den Status beizubehalten (es sind keine Felder oder Eigenschaften erforderlich), ist es immer besser, eine statische Klasse zu verwenden?
Wenn es eine beträchtliche Anzahl dieser statischen Klassendefinitionen gibt (z. B. 100 mit jeweils einer Anzahl statischer Methoden), wirkt sich dies negativ auf die Ausführungsleistung oder den Speicherverbrauch im Vergleich zur gleichen Anzahl von Instanzklassendefinitionen aus?
Tritt die Instanzauflösung immer noch auf, wenn eine andere Methode innerhalb derselben Instanzklasse aufgerufen wird? Verwenden Sie beispielsweise das Schlüsselwort [this] wie
this.DoOperation2("abc")
innerhalbDoOperation1
derselben Instanz.
quelle
this
auf etwas verweist , los , wenn eine Klasse eine Instanzmethode für sich selbst aufruft?"Antworten:
Theoretisch sollte eine statische Methode etwas besser abschneiden als eine Instanzmethode, da alle anderen Dinge aufgrund des zusätzlichen versteckten
this
Parameters gleich sind.In der Praxis macht dies so wenig Unterschied, dass es im Rauschen verschiedener Compilerentscheidungen verborgen bleibt. (Daher könnten zwei Personen eine Person mit nicht übereinstimmenden Ergebnissen besser "beweisen" als die andere). Nicht zuletzt, weil das
this
normalerweise in einem Register übergeben wird und sich oft in diesem Register befindet.Dieser letzte Punkt bedeutet, dass wir theoretisch erwarten sollten, dass eine statische Methode, die ein Objekt als Parameter verwendet und etwas damit macht, etwas weniger gut ist als das Äquivalent als Instanz für dasselbe Objekt. Auch hier ist der Unterschied so gering, dass Sie, wenn Sie versuchen würden, ihn zu messen, wahrscheinlich eine andere Compilerentscheidung messen würden. (Zumal die Wahrscheinlichkeit, dass sich diese Referenz die ganze Zeit in einem Register befindet, auch ziemlich hoch ist).
Die tatsächlichen Leistungsunterschiede hängen davon ab, ob Sie Objekte künstlich im Speicher haben, um etwas zu tun, das natürlich statisch sein sollte, oder ob Sie Ketten der Objektübergabe auf komplizierte Weise verwickeln, um das zu tun, was natürlich Instanz sein sollte.
Daher für Nummer 1. Wenn es kein Problem ist, den Status beizubehalten, ist es immer besser, statisch zu sein, denn dafür ist statisch gedacht . Es ist kein Leistungsproblem, obwohl es eine allgemeine Regel gibt, mit Compiler-Optimierungen gut zu spielen - es ist wahrscheinlicher, dass sich jemand die Mühe gemacht hat, Fälle zu optimieren, die bei normaler Verwendung auftreten, als solche, die bei seltsamer Verwendung auftreten.
Nummer 2. Macht keinen Unterschied. Es gibt eine bestimmte Menge an Kosten pro Klasse für jedes Mitglied, die sowohl davon abhängt, wie viele Metadaten vorhanden sind, wie viel Code in der tatsächlichen DLL- oder EXE-Datei vorhanden ist, als auch davon, wie viel Jitted-Code vorhanden sein wird. Dies ist gleich, ob es sich um eine Instanz oder eine statische Instanz handelt.
Mit Punkt 3
this
ist wiethis
. Beachten Sie jedoch:Der
this
Parameter wird in einem bestimmten Register übergeben. Wenn Sie eine Instanzmethode innerhalb derselben Klasse aufrufen, befindet sie sich wahrscheinlich bereits in diesem Register (es sei denn, sie wurde gespeichert und das Register aus irgendeinem Grund verwendet). Daher ist keine Aktion erforderlich, um dasthis
auf das zu setzen , worauf es eingestellt werden muss . Dies gilt bis zu einem gewissen Grad, z. B. wenn die ersten beiden Parameter der Methode die ersten beiden Parameter eines Aufrufs sind.Da klar
this
ist , dass dies nicht null ist, kann dies in einigen Fällen zur Optimierung von Anrufen verwendet werden.Da klar
this
ist , dass dies nicht null ist, kann dies dazu führen, dass inline-Methodenaufrufe wieder effizienter werden, da der Code, der zum Fälschen des Methodenaufrufs erstellt wird, einige ohnehin erforderliche Nullprüfungen weglassen kann.Das heißt, Nullschecks sind billig!
Es ist erwähnenswert, dass generische statische Methoden, die auf ein Objekt und nicht auf Instanzmethoden einwirken, einen Teil der unter http://joeduffyblog.com/2011/10/23/on-generics-and-some-of- diskutierten Kosten reduzieren können. die zugehörigen Gemeinkosten / in dem Fall, in dem die angegebene Statik für einen bestimmten Typ nicht aufgerufen wird. Wie er es ausdrückt "Nebenbei bemerkt, es stellt sich heraus, dass Erweiterungsmethoden eine großartige Möglichkeit sind, generische Abstraktionen mehr für das Spiel zu bezahlen."
Beachten Sie jedoch, dass dies nur die Instanziierung anderer von der Methode verwendeter Typen betrifft, die ansonsten nicht vorhanden sind. Als solches trifft es wirklich nicht auf viele Fälle zu (eine andere Instanzmethode verwendete diesen Typ, ein anderer Code irgendwo anders verwendete diesen Typ).
Zusammenfassung:
Bearbeiten: Ein Hinweis darauf, wie billig Null-Checks sind (was ich oben behauptet habe). Die meisten Nullprüfungen in .NET prüfen überhaupt nicht auf Null, sondern setzen ihre Arbeit mit der Annahme fort, dass sie funktionieren wird. Wenn eine Zugriffsausnahme auftritt, wird sie zu einer
NullReferenceException
. Wenn der C # -Code konzeptionell eine Nullprüfung beinhaltet, weil er auf ein Instanzmitglied zugreift, sind die Kosten, wenn er erfolgreich ist, tatsächlich Null. Eine Ausnahme wären einige Inline-Aufrufe (weil sie sich so verhalten möchten, als hätten sie ein Instanzmitglied angerufen), und sie treffen nur ein Feld, um dasselbe Verhalten auszulösen. Daher sind sie auch sehr billig und können trotzdem oft weggelassen werden (zB wenn der erste Schritt in der Methode den Zugriff auf ein Feld wie es war).quelle
this
oder über einen expliziten Parameter. Eine größere Auswirkung wäre hier, wie nahe Daten an verwandten Daten (Werttypfelder oder Arraywerte sind näher als Daten in Referenztypfeldern) und Zugriffsmuster liegen.obj.DoSomehting(2)
, die etwas billiger wäre als,DoSomething(obj, 2)
aber wie gesagt, der Unterschied ist so gering und hängt von winzigen Dingen ab, die bei der endgültigen Zusammenstellung möglicherweise anders ausfallen, dass es sich überhaupt nicht lohnt, sich Sorgen zu machen. Wenn Sie etwas tun, das so teuer ist (im Verhältnis zu den Unterschieden im Spiel), wie etwas zu einer Zeichenfolge zu serialisieren, ist es besonders sinnlos.ctor
erfordert immer noch die Initialisierung aller Felder. Sobald Sie bereits eine Instanz haben, gilt diese Antwort ("alle anderen Dinge sind gleich"). Natürlich kann ein teurescctor
Gerät auch statische Methoden verlangsamen, aber das gilt nur beim ersten Aufruf und gilt gleichermaßen für Instanzmethoden. Siehe auch docs.microsoft.com/en-us/previous-versions/dotnet/articles/…Ich würde Ja sagen. Wenn
static
Sie etwas deklarieren, erklären Sie die Absicht einer zustandslosen Ausführung (dies ist nicht obligatorisch, aber eine Absicht von etwas, das man erwarten würde).Denken Sie nicht, es sei denn, Sie sind sicher, dass statische Klassen wirklich stetig sind, denn wenn nicht, ist es einfach, Speicherzuordnungen durcheinander zu bringen und Speicherlecks zu bekommen.
Ich bin mir über diesen Punkt nicht sicher (dies ist ein reines Implementierungsdetail von CLR), aber denke ja.
quelle
statische Methoden sind schneller, aber weniger OOP. Wenn Sie Entwurfsmuster verwenden, statische Methode, wahrscheinlich schlechter Code, um Geschäftslogik besser zu schreiben, ohne statische, allgemeine Funktionen wie das Lesen von Dateien, WebRequest usw. besser als statisch zu realisieren ... Ihre Fragen sind nicht universell Antworten
quelle