Ist der as-Operator mit einem Nullwerttyp unnötig langsam?

8

Betrachten Sie diesen Code:

%Vor%

Soweit ich sehen kann, sollten die Methoden FillUsingAsNullable und FillUsingOwnCode gleichwertig sein.

Aber es sieht so aus, als wäre die Version "eigener Code" deutlich schneller.

Es gibt Optionen 2 zum Kompilieren von "x86" oder "x64" und 2 Auswahlmöglichkeiten zum Kompilieren von "Debug" oder "Release (Optimierungen)" und 3 Auswahlmöglichkeiten für was in GetObject zurückgegeben werden soll Methode. Soweit ich sehen kann, ist die Version "eigener Code" in all diesen Fällen 2*2*3 == 12 deutlich schneller als die Version "as nullable".

Die Frage: Ist as mit Nullable<> unnötig langsam, oder fehlt mir hier (ziemlich wahrscheinlich) etwas?

Zugehöriger Thread: Performanceüberraschung mit "as" - und nullable-Typen .

    
Jeppe Stig Nielsen 27.01.2014, 19:17
quelle

3 Antworten

2

Die generierte IL ist anders, aber nicht grundlegend. Wenn der JIT gut war, was nicht der Fall ist, und das keine Neuigkeiten sind, könnte dies auf genau den gleichen x86-Code kompiliert werden.

Ich habe dies mit VS2010 Release AnyCPU zusammengestellt.

as version:

%Vor%

?: version:

%Vor%

Die Beschreibungen der Opcodes sind auf MSDN. Das Verständnis dieser IL ist nicht schwierig und jeder kann es tun. Es ist ein wenig zeitaufwendig für das unerfahrene Auge, obwohl.

Der Hauptunterschied besteht darin, dass die Version mit der Verzweigung im Quelltext auch eine Verzweigung in der generierten AWL hat. Es ist nur ein bisschen weniger elegant. Der C # -Compiler hätte dies eventuell optimieren können, aber die Strategie des Teams besteht darin, sich über Optimierungen Sorgen machen zu müssen. Würde gut funktionieren, wenn die JIT dann notwendige Investitionen bekommen würde.

Sie können dies weiter analysieren, indem Sie sich das vom JIT emittierte x86 ansehen. Sie werden einen offensichtlichen Unterschied finden, aber es wird eine unspektakuläre Entdeckung sein. Ich werde nicht die Zeit dafür investieren.

Ich habe die as Version modifiziert, um auch einen temporären zu verwenden, um einen fairen Vergleich zu haben:

%Vor%     
usr 27.01.2014 20:31
quelle
0

Ja, der als Operator ist aus Gründen der Bequemlichkeit keine Leistung und daher langsamer.

Weitere Informationen finden Sie in dieser Antwort:

Wie funktioniert das "as" -Schlüsselwort intern?

    
Sham 27.01.2014 20:06
quelle
0

Ich denke, dass Ihre Testergebnisse von Messfehlern dominiert werden.

Hier ist mein Programm:

%Vor%

Hier ist, was ich in Release, außerhalb Debugger, mit return 42 :

ausführen %Vor%

Beachten Sie, dass zwischen den Läufen eine ziemlich große Varianz besteht. Sie müssten wahrscheinlich mehrere Male hintereinander laufen, um eine gute Metrik für die Leistung zu erhalten.

Folgendes geschieht, wenn wir GetObject() ändern, um (int?)42 zurückzugeben.

%Vor%

Und nochmal, mit der gleichen Konfiguration:

%Vor%

Wenn Sie wirklich aussagekräftige Daten sammeln möchten, schlage ich vor, die beiden Tests in verschiedenen Reihenfolgen mehrmals zu wiederholen und dabei den Mittelwert und die Standardabweichung zu betrachten.

Ich vermute, dass die größte Zeitsenke bei diesen Methoden die Ungültigkeit des Speichercache ist, so dass das Ergebnis für einen gegebenen Test wahrscheinlich davon abhängt, wo genau das Array für jeden Test zugewiesen wird und wann GC während der häufigen Boxzuweisungen eintritt .

    
Dan Bryant 27.01.2014 21:01
quelle