现净switch语句散列或索引? [英] Are .Net switch statements hashed or indexed?

查看:278
本文介绍了现净switch语句散列或索引?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

难道.NET 4中(或任何早期版本)基于字符串长switch语句进行任何优化?

Does .Net 4 (or any prior version) perform any sort of optimization on longer switch statements based on strings?

我身边潜在的性能瓶颈的工作,由于一些长期switch语句寻找的情况下匹配的字符串,而我一直认为这些被搜查的线性时间(或接近线性的,即不使用索引以便快速查找匹配的字符串)。但是,这似乎是一个明显区域的.Net可以优化,所以认为我会检查,如果是这样的话还是不行。

I'm working around a potential performance bottleneck due to some long switch statements looking for matching strings in the cases, and I've always assumed these are searched in linear time (or near linear, i.e. not using an index to quickly find the matching string). But this seems like an obvious area that .Net could optimize, so thought I'd check if this is the case or not.

这是从我最近的一个衍生问题:<一href="http://stackoverflow.com/questions/3365677/indexed-switch-statement-or-equivalent-net-c">http://stackoverflow.com/questions/3365677/indexed-switch-statement-or-equivalent-net-c

This is a derivative question from my recent one: http://stackoverflow.com/questions/3365677/indexed-switch-statement-or-equivalent-net-c

推荐答案

编译下面code。

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

现在使用反射 ILDASM 检查白细胞介素的C#编译器生成。不断增加的情况下语句和反编译并观察结果。

Now use Reflector or ILDASM to examine the IL the C# compiler generates. Keep adding case statements and decompiling and observe the result.

  • 如果case语句的数量较小,则编译器会发出连续的相等比较。
  • 如果case语句的数量大,则编译器会发出词典查找。
  • If the number of case statements is small then the compiler emits a sequential equality comparison.
  • If the number of case statements is large then the compiler emits a Dictionary lookup.

我用的是C#3.0编译器,我观察到,该战略在7 case语句变化。我怀疑你会看到类似的东西在C#4.0等。

I was using the C# 3.0 compiler and I observed that the strategy changes at 7 case statements. I suspect you will see something similiar with C# 4.0 and others.

更新:

我要指出,你会看到调用 Dictionary.Add 中的白细胞介素输出在那里建立词典以备后用。不要误以为出现这种情况每次。编译器实际上是生成一个单独的静态类和做它内联静态初始化。要特别注意的指令在L_0026。如果类已经被初始化然后在该分支将跳过了添加的电话。

I should point that you will see calls to Dictionary.Add in the IL output where it is building up the dictionary for later use. Do not be fooled into thinking this happens everytime. The compiler is actually generating a separate static class and doing an inline static initialization of it. Pay particular attention to the instruction at L_0026. If the class is already initialized then the branch will skip over the Add calls.

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)

另外,注意字典实际上包含从原来的字符串为整数的映射。此整数用于配制在IL一个单独的开关。

Also, notice that the dictionary actually contains a map from the original string to an integer. This integer is used to formulate a separate switch in 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 

更新2:

对于什么是值得VB.NET似乎并不具有同样的优化,其选择结构。

For what it is worth VB.NET does not seem to have this same optimization for its Select construct.

这篇关于现净switch语句散列或索引?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆