3 回答
TA贡献1877条经验 获得超1个赞
这是我的原帖,引发了一些争论...... 因为它错了:
switch语句与if-else语句不同。每个案例必须是唯一的并且静态评估。无论您有多少个案例,switch语句都会执行一个恒定时间分支。if-else语句计算每个条件,直到找到一个为真。
实际上,C#switch语句并不总是一个恒定时间分支。
在某些情况下,编译器将使用CIL开关语句,该语句确实是使用跳转表的恒定时间分支。然而,在Ivan Hamilton指出的稀疏情况下,编译器可能完全生成其他东西。
这实际上很容易通过编写各种C#switch语句来验证,一些稀疏,一些密集,并使用ildasm.exe工具查看生成的CIL。
TA贡献1871条经验 获得超13个赞
重要的是不要将C#switch语句与CIL开关指令混淆。
CIL开关是一个跳转表,需要索引到一组跳转地址。
这仅在C#开关的情况相邻时才有用:
case 3: blah; break;case 4: blah; break;case 5: blah; break;
但如果不是这样的话,几乎没用:
case 10: blah; break;case 200: blah; break;case 3000: blah; break;
(你需要一个表~3000个条目,只使用3个插槽)
对于非相邻表达式,编译器可能会开始执行线性if-else-if-else检查。
对于较大的非相邻表达式集,编译器可以从二叉树搜索开始,最后是if-else-if-else最后几个项。
对于包含相邻项块的表达式集,编译器可以进行二叉树搜索,最后是CIL开关。
这充满了“mays”和“mights”,它依赖于编译器(可能与Mono或Rotor不同)。
我使用相邻的案例在我的机器上复制了你的结果:
执行10路开关的总时间,10000次迭代(ms):
每10路开关25.1383 近似时间(ms):0.00251383执行50路开关的总时间,10000次迭代(ms):
每50路开关的大约时间为26.593 (ms):0.0026593执行5000路开关的总时间,10000次迭代(ms):23.7094
每5000路开关的近似时间(ms):0.00237094执行50000路开关的总时间,10000次迭代(ms):20.0933
每50000路开关的近似时间(ms):0.00200933
然后我也使用了非相邻的case表达式:
执行10路开关的总时间,10000次迭代(ms):19.6189
每10路开关的近似时间(ms):0.00196189执行500路开关的总时间,10000次迭代(ms):
每个500路开关的近似时间为19.1664 (ms):0.00191664执行5000路开关的总时间,10000次迭代(ms):
每5000路开关的大约时间为19.5871 (ms):0.00195871不相邻的50,000个案例切换语句将无法编译。
“在'ConsoleApplication1.Program.Main(string [])'附近编译表达式太长或太复杂
这里有趣的是,二叉树搜索比CIL切换指令更快(可能不是统计上)。
Brian,你使用了“ 常量 ” 这个词,从计算复杂性理论的角度来看,它具有非常明确的含义。虽然简化的相邻整数示例可以产生被认为是O(1)(常数)的CIL,但稀疏示例是O(log n)(对数),聚类示例介于两者之间,小例子是O(n)(线性) )。
这甚至不能解决Generic.Dictionary<string,int32>
可能会创建静态的String情况,并且在首次使用时会遇到明确的开销。这里的表现将取决于表现Generic.Dictionary
。
如果检查C#语言规范(不是CIL规范),你会发现“15.7.2 switch语句”没有提到“常量时间”或底层实现甚至使用CIL开关指令(要非常小心假设这样的事情)。
在一天结束时,针对现代系统上的整数表达式的C#切换是亚微秒操作,通常不值得担心。
当然,这些时间将取决于机器和条件。我不会注意这些时序测试,我们所讨论的微秒持续时间与正在运行的任何“真实”代码相比相形见绌(并且您必须包含一些“真实代码”,否则编译器将优化分支),或者系统中的抖动。我的答案基于使用IL DASM来检查C#编译器创建的CIL。当然,这不是最终的,因为CPU运行的实际指令随后由JIT创建。
我检查了在我的x86机器上实际执行的最终CPU指令,并且可以确认一个简单的相邻设置开关,例如:
jmp ds:300025F0[eax*4]
二叉树搜索满满的地方:
cmp ebx, 79Eh jg 3000352B cmp ebx, 654h jg 300032BB … cmp ebx, 0F82h jz 30005EEE
- 3 回答
- 0 关注
- 733 浏览
添加回答
举报