22 Stimmen

Leistungsüberhang für Eigenschaften in .NET

Ich habe irgendwo gelesen, dass es besser ist, öffentliche Eigenschaften zu haben, als öffentliche Mitglieder in einer Klasse zu haben.

  1. Liegt das nur an der Abstraktion und der Modularität? Gibt es noch andere Gründe, die übergeordnet sind?

  2. Die Eigenschaftszugriffe werden vom Compiler in Funktionsaufrufe umgewandelt. Für Eigenschaften ohne Backup-Speicher (z.B. public string UserName { get; set; } ), wie hoch wäre der Leistungsaufwand im Vergleich zu einem direkten Mitgliederzugriff? (Ich weiß, dass es normalerweise keinen Unterschied machen sollte, aber in einigen meiner Codes wird millionenfach auf Eigenschaften zugegriffen).

Bearbeiten1: Ich habe einige Testcodes über Integer-Mitglieder und Eigenschaften ausgeführt und die öffentlichen Mitglieder waren etwa 3-4 Mal so schnell wie die Eigenschaften. (~57 ms. vs. ~206 ms. in Debug und 57 vs. 97 in Release war der häufigste Laufwert). Bei 10 Millionen Lese- und Schreibvorgängen sind beide Werte klein genug, um eine Änderung nicht zu rechtfertigen.

Code:

    class TestTime1
{
    public TestTime1() { }
    public int id=0;
}
class TestTime2
{
    public TestTime2() { }
    [DefaultValue(0)]
    public int ID { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        try
        {
            TestTime1 time1 = new TestTime1();
            TestTime2 time2 = new TestTime2();
            Stopwatch watch1 = new Stopwatch();
            Stopwatch watch2 = new Stopwatch();
            watch2.Start();
            for (int i = 0; i < 10000000; i++)
            {
                time2.ID = i;
                i = time2.ID;
            }
            watch2.Stop();
            watch1.Start();
            for (int i = 0; i < 10000000; i++)
            {
                time1.id = i;
                i = time1.id;
            }
            watch1.Stop();
            Console.WriteLine("Time for 1 and 2 : {0},{1}",watch1.ElapsedMilliseconds,watch2.ElapsedMilliseconds);

        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        Console.In.ReadLine();
    }
}

21voto

Hans Passant Punkte 894572

Der Test wird 20 Mal hintereinander ausgeführt, wobei sichergestellt wird, dass die JIT-Optimierung im Release-Build aktiviert ist:

Time for 1 and 2 : 47,66
Time for 1 and 2 : 37,42
Time for 1 and 2 : 25,36
Time for 1 and 2 : 25,25
Time for 1 and 2 : 27,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 26,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25

Ja, der JITter ist dass gut im Inlining von Property-Accessors. Perf ist ein Nicht-Problem und sollte nie in Betracht gezogen werden.

18voto

Steven Sudit Punkte 19005

Machen Sie sich keine Sorgen wegen des Leistungsaufwands. Er ist so gering, dass Sie nicht in Erwägung ziehen sollten, die Kapselung der Klasse zu schwächen; das wäre eine verfrühte Optimierung der schlimmsten Art.

9voto

Thomas Punkte 160390

Liegt das nur an der Abstraktion und der Modularität? Gibt es noch andere Gründe, die übergeordnet sind?

Nicht, dass ich wüsste; diese Gründe sind an sich schon zwingend genug. Aber vielleicht meldet sich ja noch jemand zu Wort.

Die Eigenschaftszugriffe werden vom Compiler in Funktionsaufrufe umgewandelt. Für Eigenschaften ohne Backup-Speicher (z.B. public string UserName { get; set; }), was wäre der Performance-Overhead im Vergleich zu einem direkten Memberzugriff? (Ich weiß, dass es normalerweise keinen Unterschied machen sollte, aber in einigen meiner Codes wird millionenfach auf Eigenschaften zugegriffen).

In der resultierenden Intermediate Language wird ein Eigenschaftszugriff in einen Methodenaufruf übersetzt. Wie das Wort schon sagt, handelt es sich jedoch nur um eine Zwischensprache: Sie wird Just-In-Time in etwas anderes übersetzt. Dieser Übersetzungsschritt umfasst auch Optimierungen wie das Inlining trivialer Methoden, z. B. einfacher Eigenschaftszugriffe.

Ich würde erwarten (aber Sie müssten testen, um sicher zu sein), dass der JITter kümmert sich um solche Accessors, so sollte es keinen Leistungsunterschied sein.

4voto

Rowland Shaw Punkte 37027

Sie dient hauptsächlich der Abstraktion (Sie können später eine Validierung hinzufügen, ohne den bestehenden Code zu zerstören oder eine Neukompilierung zu erfordern).

Auch bei der Verwendung von Auto-Properties gibt es immer noch ein vom Compiler generiertes Backing-Feld, das auch als solches funktioniert.

3voto

Dax Fohl Punkte 10360

Vergewissern Sie sich, dass Sie mit Strg-F5 statt mit F5 arbeiten; andernfalls wird der Debugger immer noch angehängt, und einige Optimierungen funktionieren möglicherweise nicht auf die gleiche Weise, selbst im Release-Modus. Zumindest ist das auf meinem Rechner der Fall: F5 liefert ähnliche Ergebnisse wie das, was Sie gepostet haben, während Ctrl-F5 die gleichen Ergebnisse liefert.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X