microbenchmark

___ tag123c ___ C # (sprich "Cis") ist eine objektorientierte Programmiersprache auf hohem Niveau, die für die Erstellung einer Vielzahl von Anwendungen entworfen wurde, die auf dem .NET Framework (oder .NET Core) ausgeführt werden. C # ist einfach, leistungsfähig, typsicher und objektorientiert. ___ tag123microenchmark ___ Ein Microbenchmark versucht, die Leistung eines "kleinen" Bitcodes zu messen. Diese Tests liegen typischerweise im Bereich von unter einer Millisekunde. Der getestete Code führt normalerweise keine E / A durch oder ist ein Test für eine einzelne spezifische E / A-Task. ___ tag123net47 ___ .NET 4.7 ist die neueste Framework-Version von Microsoft. Es ist eine Nachfolge zu .NET-4.6 und im Windows 10 Creators Update enthalten. ___ qstntxt ___

Ich habe das Problem, wo ich basierend auf einem Objekttyp dynamischen Versand durchführen muss. Die Typen, auf deren Grundlage ich versenden muss, sind zur Kompilierzeit bekannt - in meinem Beispiel sind sie 17 .

Meine anfängliche Schätzung war, ein %code% für das Versenden zu verwenden und %code% zu verwenden, um die entsprechende Aktion herauszufinden. Aber dann entschied ich mich, BenchmarkDotNet zu verwenden, um zu sehen, ob ich besser und genauer tun kann, wie teuer die Versandsuche sein würde. Bellow ist der Code, den ich für den Benchmark verwendet habe.

%Vor%

In meinem Beispiel habe ich den Test mit einem Boxed Guid durchgeführt, was der schlimmste Fall in der handgefertigten Switch-Funktion ist. Die Ergebnisse waren überraschend, um es gelinde auszudrücken:

%Vor%

Die Switch-Funktion ist im schlimmsten Fall 2-mal schneller. Wenn ich die IFS so umordne, dass die häufigsten Typen zuerst sind, dann erwarte ich im Durchschnitt, dass sie 3-5 mal schneller läuft.

Meine Frage ist, wie kommt es, dass 18 Checks so viel schneller sind als ein einzelnes Wörterbuch? Fehle ich etwas Offensichtliches?

BEARBEITEN:

Der ursprüngliche Test war der x86-Modus (Prefer 32bit) auf dem x64-Computer. Ich habe die Tests auch in 64 Release Builds durchgeführt:

%Vor%     
___ qstnhdr ___ Beim Vergleichen von Dictionary-Lookup und multiplen is-Operatoren in .NET 4.7 treten unerwartete Leistungsergebnisse auf ___ answer48008375 ___

Ich bin keineswegs ein IL-Performance-Guru, aber wenn Sie die IL dekompilieren und besonders betrachten, ergibt das Sinn.

Der %code% Operator ist nur 4 Opcodes (ldarg, isinst, ldnull, cgt), und jeder switch Teil nur 7 insgesamt mit dem hinzugefügten goto. Der Aktionsteil von %code% zum Aufruf von %code% ist dann weitere 6, geben 17 * 7 + 6 = 125 max.

Im Gegensatz dazu ist %code% möglicherweise nur ein Methodenaufruf, aber innerhalb dieses Prozesses werden viele Werte für Hashing, Schleifen und Vergleichen verarbeitet:

Ссылка

%Vor%

Ссылка

%Vor%

Die for-Schleife in %code% allein ist 31 Opcodes für jede Schleife, was maximal 527 Opcodes nur für diesen Teil ergibt.

Dies ist eine sehr einfache Analyse, aber es ist leicht zu erkennen, dass der Switch leistungsfähiger sein sollte. Wie es häufig der Fall ist, müssen Sie Leistung gegenüber Lesbarkeit und Wartbarkeit berücksichtigen. Wenn Sie einen Dictionary-Lookup verwenden, der Ihnen einen besseren Code bietet, ist es selten, dass der Leistungsverlust (15ns) diesen Nutzen überwiegt.

    
___
1
Antwort

Was kann die enorme Leistungseinbuße beim Schreiben eines Verweises auf einen Heap-Speicherort erklären?

Bei der Untersuchung der subtileren Konsequenzen von generationsbedingten Speicherbereinigungen auf die Anwendungsleistung habe ich eine ziemlich erstaunliche Diskrepanz in der Leistung einer sehr einfachen Operation - eines einfachen Schreibens...
03.02.2014, 09:44
1
Antwort

Schätzung der tatsächlichen (nicht theoretischen) Laufzeitkomplexität einer Implementierung

Jeder in der Informatik weiß, dass HeapSort in der Theorie der theoretisch schlimmste Fall ist, während QuickSort im schlimmsten Fall O(n log n) ist. In der Praxis wird jedoch ein gut implementiertes QuickSort (mit guten Heuristiken) HeapSort...
05.07.2013, 16:52
1
Antwort

Die Befehlspipeline von Intel Core 2 Duo leeren?

Ich schreibe einige Mikro-Benchmark-Code für einige sehr kurze Operationen in C. Zum Beispiel, eine Sache, die ich messe ist, wie viele Zyklen benötigt werden, um eine leere Funktion abhängig von der Anzahl der Argumente zu nennen. Momentan v...
22.02.2009, 17:52
2
Antworten

Groovy: Ist for..in wesentlich schneller als .each?

Ich bin gespannt, ob for..in aus Leistungsgründen der .each vorgezogen werden sollte.     
05.06.2015, 08:38
1
Antwort

Beim Vergleichen von Dictionary-Lookup und multiplen is-Operatoren in .NET 4.7 treten unerwartete Leistungsergebnisse auf

Ich habe das Problem, wo ich basierend auf einem Objekttyp dynamischen Versand durchführen muss. Die Typen, auf deren Grundlage ich versenden muss, sind zur Kompilierzeit bekannt - in meinem Beispiel sind sie 17 . Meine anfängliche Schätzung...
28.12.2017, 12:39