Warum sind Arrays (Vektoren) so langsam?

8

Ich hatte den Eindruck, dass .NET-Casting (nicht konvertieren) sehr billig und schnell ist. Dies scheint jedoch für Array nicht der Fall zu sein. Ich versuche hier eine sehr einfache Besetzung zu machen, nimm ein T1 [] und wirf als T2 []. wo T1: T2.

Es gibt 3 Möglichkeiten, dies zu tun, und ich nenne sie die folgenden ::

%Vor%

Und ich habe Methoden dafür entwickelt, leider scheint C # ziemlich seltsamen Code zu erzeugen, abhängig davon, ob das generisch ist oder nicht. (Wenn das generische DropCasting den Castclass-Operator verwendet. Und in beiden Fällen wird die Ausgabe eines 'as'-Operators abgelehnt, wenn T1: T2.

Wie auch immer, ich schrieb einige Dynamische Methoden und testete sie mit überraschenden Ergebnissen (string [] = & gt; object []):

%Vor%

Dropcasting war ~ 18 mal schneller als jeder der Cast-Operatoren. Warum ist das Gießen für Arrays so langsam? Für normale Objekte wie String = & gt; -Objekt war der Unterschied viel weniger streng.

%Vor%

Benchmarkcode unten:

%Vor%

Bearbeite, bevor jemand die gleiche Frage für Dinge wie int [] - & gt; uint [] stellt, die die clr-Spezifikationen ohne Konvertierung umgewandelt werden sollen.

    
Michael B 28.09.2011, 20:45
quelle

2 Antworten

0

Weil Sie Arrays umwandeln.

Der Unterschied zwischen den 3 Snippets von IL-Code besteht darin, dass die letzten beiden eine IsInst- und eine CastClass-Operation hinzufügen. Über die Typen ist sehr wenig bekannt, daher muss die CLR prüfen, ob es sich um eine gültige Operation handelt. Das braucht Zeit.

Der geringe Unterschied zwischen CastClass und IsInst kann durch die Tatsache erklärt werden, dass CastClass zuerst eine Nullprüfung durchführt und sofort erfolgreich ist, wenn das Argument null ist.

Ich vermute, dass die Verlangsamung darauf zurückzuführen ist, dass Sie zwischen Arrays wechseln. Es muss möglicherweise viel mehr Arbeit geleistet werden, um sicherzustellen, dass ein Array-Cast gültig ist. Es kann notwendig sein, jedes Element zu betrachten, um zu sehen, ob es in den Zielelementtyp umgewandelt werden kann. Also würde ich vermuten, dass das JIT, statt all dies in "inline" -Maschinencode zu tun, einen Aufruf an eine Validierungsfunktion sendet.

Wenn Sie eine Leistungsanalyse durchführen, können Sie tatsächlich sehen, dass dies tatsächlich geschieht. Fast 90% der Zeit wird in einer Funktion namens "JIT_ChkCastArray" verbracht.

    
Jeffrey Sax 28.09.2011, 22:59
quelle
0

Es macht für mich Sinn, dass Casting (fast) genau so teuer ist wie der Operator as . In beiden Szenarien muss eine Laufzeitprüfung auf den Typ des Objekts durchgeführt werden und es muss festgestellt werden, ob es mit dem Zieltyp kompatibel ist. Die Überprüfung ist erforderlich, damit der Cast-Vorgang bei Bedarf ein InvalidCastException auslösen kann.

Um es anders auszudrücken, der as operator ist eine Cast-Operation - er hat auch den Vorteil, dass der Cast fehlschlagen kann, ohne eine Ausnahme auszulösen (indem er null zurückgibt). Dies könnte auch mit einer Kombination des is -Operators und einem Cast erfolgen, aber das würde die Arbeitsbelastung verdoppeln.

    
Kirk Woll 28.09.2011 21:16
quelle

Tags und Links