46 votes

Les instructions de commutateur .Net sont-elles hachées ou indexées?

N' .Net 4 (ou toute version antérieure) s'acquitter de toute sorte de l'optimisation de l'allongement de l'interrupteur des déclarations fondées sur des chaînes?

Je suis en train de travailler autour d'un éventuel goulot d'étranglement des performances en raison de certaines instructions de commutation à la recherche pour la mise en correspondance des chaînes dans le cas, et j'ai toujours supposé que ces sont recherchés dans le temps linéaire (ou quasi-linéaire, c'est à dire de ne pas utiliser un index pour trouver rapidement la chaîne correspondante). Mais cela semble être un domaine évident que .Net pourrait optimiser, donc pensé que je voudrais vérifier si c'est le cas ou pas.

C'est un dérivé de la question de mon récent: http://stackoverflow.com/questions/3365677/indexed-switch-statement-or-equivalent-net-c

114voto

Brian Gideon Points 26683

Compiler le code suivant.

public static int Main(string[] args)
{
    switch (args[0])
    {
        case "x": return 1;
        case "y": return 2;
        case "z": return 3;
    }
    return 0;
}

Maintenant, utilisez un Réflecteur ou ILDASM pour examiner le IL le compilateur C# génère. Continuez à ajouter des cas de déclarations et de décompilation et d'observer le résultat.

  • Si le nombre de cas annuels est petit, puis le compilateur émet une séquence de comparaison d'égalité.
  • Si le nombre de cas annuels est grand alors le compilateur émet un Dictionary de recherche.

J'ai été en utilisant le C# 3.0 compilateur et j'ai observé que les changements de stratégie à 7 cas de déclarations. Je soupçonne que vous verrez quelque chose de similaire avec C# 4.0 et d'autres.

Mise à jour:

Je tiens à souligner que vous pourrez voir les appels d' Dictionary.Add dans le IL sortie où elle est la construction du dictionnaire pour les utiliser plus tard. Ne vous laissez pas berner en pensant que ce qui se passe à chaque fois. Le compilateur est en fait la génération d'un distinct statique de la classe et de faire une ligne initialisation statique d'elle. Accorder une attention particulière à l'instruction à L_0026. Si la classe est déjà initialisé alors la branche va ignorer l' Add des appels.

L_0021: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2<string, int32> <PrivateImplementationDetails>{816396DD-F271-4C12-83D0-CC9C9CD67AD6}::$$method0x6000001-1
L_0026: brtrue.s L_0089
L_0028: ldc.i4.7 
L_0029: newobj instance void [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::.ctor(int32)
L_002e: dup 
L_002f: ldstr "x"
L_0034: ldc.i4.0 
L_0035: call instance void [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::Add(!0, !1)
L_003a: dup 
L_003b: ldstr "y"
L_0040: ldc.i4.1 
L_0041: call instance void [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::Add(!0, !1)
L_0046: dup 
L_0047: ldstr "z"
L_004c: ldc.i4.2 
L_004d: call instance void [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::Add(!0, !1)

Notez également que le dictionnaire contient en fait une carte de la chaîne d'origine à un entier. Cet entier est utilisé pour formuler un interrupteur séparé en IL.

L_0089: volatile. 
L_008b: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2<string, int32> <PrivateImplementationDetails>{816396DD-F271-4C12-83D0-CC9C9CD67AD6}::$$method0x6000001-1
L_0090: ldloc.2 
L_0091: ldloca.s CS$0$0002
L_0093: call instance bool [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::TryGetValue(!0, !1&)
L_0098: brfalse.s L_00da
L_009a: ldloc.3 
L_009b: switch (L_00be, L_00c2, L_00c6, L_00ca, L_00ce, L_00d2, L_00d6)
L_00bc: br.s L_00da
L_00be: ldc.i4.1 
L_00bf: stloc.1 
L_00c0: br.s L_00de
L_00c2: ldc.i4.2 
L_00c3: stloc.1 
L_00c4: br.s L_00de
L_00c6: ldc.i4.3 

Mise à jour 2:

Pour ce qu'il vaut VB.NET ne semble pas avoir ce même optimisation pour son Select construire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X