[VB] if 判断语句 和 If、IIf函数的比较
1 Module Module1 2 Sub Main() 3 Dim i As Integer = 1 4 Dim s1 As String = "我是真的" 5 Dim s2 As String = "我不是真的" 6 Dim s3 As String 7 Dim mx As Integer = 1000000000 8 Dim start As DateTime 9 10 For iii As Integer = 0 To 9 11 start = DateTime.Now 12 For ii As Integer = 0 To mx 13 If i = 0 Then 14 s3 = s1 15 Else 16 s3 = s2 17 End If 18 Next 19 Console.WriteLine((DateTime.Now - start).TotalMilliseconds) 20 21 start = DateTime.Now 22 For ii As Integer = 0 To mx 23 s3 = If(i = 0, s1, s2) 24 Next 25 Console.WriteLine((DateTime.Now - start).TotalMilliseconds) 26 27 start = DateTime.Now 28 For ii As Integer = 0 To mx 29 s3 = IIf(i = 0, s1, s2) 30 Next 31 Console.WriteLine((DateTime.Now - start).TotalMilliseconds) 32 33 Console.WriteLine("--------------------------------") 34 Next 35 End Sub 36 End Module
执行结果:
2628.1503
2377.1359
6495.3716
--------------------------------
2602.1488
2390.1367
6535.3738
--------------------------------
2579.1475
2414.1381
6532.3736
--------------------------------
2651.1516
2405.1376
6627.3791
--------------------------------
2641.151
2390.1367
6538.374
--------------------------------
2619.1498
2398.1371
6656.3807
--------------------------------
2716.1554
2441.1396
6574.3761
--------------------------------
2623.15
2451.1402
6618.3786
--------------------------------
2650.1516
2409.1378
6550.3747
--------------------------------
2669.1527
2425.1387
6683.3823
--------------------------------
看结果很明显,效率上:If-Else 略大于 If(Express,SelectValue1,SelectValue2) 大于 IIf(Express,SelectValue1,SelectValue2)
这是为什么呢?
先看全部的IL(当然也可以略去不看,下面我已经将重要片段给截取出来做了比较,提示:本题中大部分指令已在本文结尾处做了注释)
1 --- D:\Moontest\ConsoleApplication1\Module1.vb --------------------------------- 2 Dim i As Integer = 1 3 00000000 push ebp 4 00000001 mov ebp,esp 5 00000003 push edi 6 00000004 push esi 7 00000005 sub esp,108h 8 0000000b lea edi,[ebp+FFFFFEF0h] 9 00000011 mov ecx,40h 10 00000016 xor eax,eax 11 00000018 rep stos dword ptr es:[edi] 12 0000001a cmp dword ptr ds:[004B1538h],0 13 00000021 je 00000028 14 00000023 call 682F477C 15 00000028 xor edx,edx 16 0000002a mov dword ptr [ebp+FFFFFF00h],edx 17 00000030 xor edx,edx 18 00000032 mov dword ptr [ebp+FFFFFF04h],edx 19 00000038 xor edx,edx 20 0000003a mov dword ptr [ebp+FFFFFEFCh],edx 21 00000040 xor edx,edx 22 00000042 mov dword ptr [ebp-10h],edx 23 00000045 xor edx,edx 24 00000047 mov dword ptr [ebp-0Ch],edx 25 0000004a xor edx,edx 26 0000004c mov dword ptr [ebp-24h],edx 27 0000004f xor edx,edx 28 00000051 mov dword ptr [ebp-20h],edx 29 00000054 xor edx,edx 30 00000056 mov dword ptr [ebp-1Ch],edx 31 00000059 xor edx,edx 32 0000005b mov dword ptr [ebp+FFFFFF6Ch],edx 33 00000061 xor edx,edx 34 00000063 mov dword ptr [ebp+FFFFFF68h],edx 35 00000069 xor edx,edx 36 0000006b mov dword ptr [ebp-28h],edx 37 0000006e mov dword ptr [ebp-0Ch],1 38 Dim s1 As String = "我是真的" 39 00000075 mov eax,dword ptr ds:[033C2194h] 40 0000007b mov dword ptr [ebp+FFFFFF04h],eax 41 Dim s2 As String = "我不是真的" 42 00000081 mov eax,dword ptr ds:[033C2198h] 43 00000087 mov dword ptr [ebp+FFFFFF00h],eax 44 Dim s3 As String 45 Dim mx As Integer = 1000000000 46 0000008d mov dword ptr [ebp-10h],3B9ACA00h 47 Dim start As DateTime 48 49 'For iii As Integer = 0 To 9 50 start = DateTime.Now 51 00000094 lea ecx,[ebp+FFFFFF60h] 52 0000009a call 6678EAC8 53 0000009f lea edi,[ebp-18h] 54 000000a2 lea esi,[ebp+FFFFFF60h] 55 000000a8 movq xmm0,mmword ptr [esi] 56 000000ac movq mmword ptr [edi],xmm0 57 For ii As Integer = 0 To mx 58 000000b0 mov eax,dword ptr [ebp-10h] 59 000000b3 mov dword ptr [ebp-28h],eax 60 000000b6 xor edx,edx 61 000000b8 mov dword ptr [ebp-1Ch],edx 62 000000bb nop 63 000000bc jmp 000000EA 64 If i = 0 Then 65 000000be cmp dword ptr [ebp-0Ch],0 66 000000c2 jne 000000D3 67 s3 = s1 68 000000c4 mov eax,dword ptr [ebp+FFFFFF04h] 69 000000ca mov dword ptr [ebp+FFFFFEFCh],eax 70 000000d0 nop 71 000000d1 jmp 000000DF 72 Else 73 s3 = s2 74 000000d3 mov eax,dword ptr [ebp+FFFFFF00h] 75 000000d9 mov dword ptr [ebp+FFFFFEFCh],eax 76 End If 77 Next 78 000000df add dword ptr [ebp-1Ch],1 79 000000e3 jno 000000EA 80 000000e5 call 682F3C1A 81 000000ea mov eax,dword ptr [ebp-1Ch] 82 000000ed cmp eax,dword ptr [ebp-28h] 83 000000f0 jle 000000BE 84 Console.WriteLine((DateTime.Now - start).TotalMilliseconds) 85 000000f2 lea ecx,[ebp+FFFFFF58h] 86 000000f8 call 6678EAC8 87 000000fd lea eax,[ebp+FFFFFF58h] 88 00000103 sub esp,8 89 00000106 movq xmm0,mmword ptr [eax] 90 0000010a movq mmword ptr [esp],xmm0 91 0000010f lea eax,[ebp-18h] 92 00000112 sub esp,8 93 00000115 movq xmm0,mmword ptr [eax] 94 00000119 movq mmword ptr [esp],xmm0 95 0000011e lea ecx,[ebp+FFFFFF50h] 96 00000124 call 6678A950 97 00000129 lea edi,[ebp+FFFFFF70h] 98 0000012f lea esi,[ebp+FFFFFF50h] 99 00000135 movq xmm0,mmword ptr [esi] 100 00000139 movq mmword ptr [edi],xmm0 101 0000013d lea ecx,[ebp+FFFFFF70h] 102 00000143 call 6678DD38 103 00000148 fstp qword ptr [ebp+FFFFFF48h] 104 0000014e fld qword ptr [ebp+FFFFFF48h] 105 00000154 sub esp,8 106 00000157 fstp qword ptr [esp] 107 0000015a call 66E72E20 108 109 start = DateTime.Now 110 0000015f lea ecx,[ebp+FFFFFF40h] 111 00000165 call 6678EAC8 112 0000016a lea edi,[ebp-18h] 113 0000016d lea esi,[ebp+FFFFFF40h] 114 00000173 movq xmm0,mmword ptr [esi] 115 00000177 movq mmword ptr [edi],xmm0 116 For ii As Integer = 0 To mx 117 0000017b mov eax,dword ptr [ebp-10h] 118 0000017e mov dword ptr [ebp+FFFFFF6Ch],eax 119 00000184 xor edx,edx 120 00000186 mov dword ptr [ebp-20h],edx 121 00000189 nop 122 0000018a jmp 000001C4 123 s3 = If(i = 0, s1, s2) 124 0000018c cmp dword ptr [ebp-0Ch],0 125 00000190 je 000001A1 126 00000192 nop 127 00000193 mov eax,dword ptr [ebp+FFFFFF00h] 128 00000199 mov dword ptr [ebp+FFFFFEF8h],eax 129 0000019f jmp 000001AD 130 000001a1 mov eax,dword ptr [ebp+FFFFFF04h] 131 000001a7 mov dword ptr [ebp+FFFFFEF8h],eax 132 000001ad mov eax,dword ptr [ebp+FFFFFEF8h] 133 000001b3 mov dword ptr [ebp+FFFFFEFCh],eax 134 Next 135 000001b9 add dword ptr [ebp-20h],1 136 000001bd jno 000001C4 137 000001bf call 682F3C1A 138 000001c4 mov eax,dword ptr [ebp-20h] 139 000001c7 cmp eax,dword ptr [ebp+FFFFFF6Ch] 140 000001cd jle 0000018C 141 Console.WriteLine((DateTime.Now - start).TotalMilliseconds) 142 000001cf lea ecx,[ebp+FFFFFF38h] 143 000001d5 call 6678EAC8 144 000001da lea eax,[ebp+FFFFFF38h] 145 000001e0 sub esp,8 146 000001e3 movq xmm0,mmword ptr [eax] 147 000001e7 movq mmword ptr [esp],xmm0 148 000001ec lea eax,[ebp-18h] 149 000001ef sub esp,8 150 000001f2 movq xmm0,mmword ptr [eax] 151 000001f6 movq mmword ptr [esp],xmm0 152 000001fb lea ecx,[ebp+FFFFFF30h] 153 00000201 call 6678A950 154 00000206 lea edi,[ebp-30h] 155 00000209 lea esi,[ebp+FFFFFF30h] 156 0000020f movq xmm0,mmword ptr [esi] 157 00000213 movq mmword ptr [edi],xmm0 158 00000217 lea ecx,[ebp-30h] 159 0000021a call 6678DD38 160 0000021f fstp qword ptr [ebp+FFFFFF28h] 161 00000225 fld qword ptr [ebp+FFFFFF28h] 162 0000022b sub esp,8 163 0000022e fstp qword ptr [esp] 164 00000231 call 66E72E20 165 166 start = DateTime.Now 167 00000236 lea ecx,[ebp+FFFFFF20h] 168 0000023c call 6678EAC8 169 00000241 lea edi,[ebp-18h] 170 00000244 lea esi,[ebp+FFFFFF20h] 171 0000024a movq xmm0,mmword ptr [esi] 172 0000024e movq mmword ptr [edi],xmm0 173 For ii As Integer = 0 To mx 174 00000252 mov eax,dword ptr [ebp-10h] 175 00000255 mov dword ptr [ebp+FFFFFF68h],eax 176 0000025b xor edx,edx 177 0000025d mov dword ptr [ebp-24h],edx 178 00000260 nop 179 00000261 jmp 000002AC 180 s3 = IIf(i = 0, s1, s2) 181 00000263 push dword ptr [ebp+FFFFFF00h] 182 00000269 cmp dword ptr [ebp-0Ch],0 183 0000026d sete cl 184 00000270 movzx ecx,cl 185 00000273 mov edx,dword ptr [ebp+FFFFFF04h] 186 00000279 call 55FD3238 187 0000027e mov dword ptr [ebp+FFFFFEF4h],eax 188 00000284 mov ecx,dword ptr [ebp+FFFFFEF4h] 189 0000028a call 55FAFAA0 190 0000028f mov dword ptr [ebp+FFFFFEF0h],eax 191 00000295 mov eax,dword ptr [ebp+FFFFFEF0h] 192 0000029b mov dword ptr [ebp+FFFFFEFCh],eax 193 Next 194 000002a1 add dword ptr [ebp-24h],1 195 000002a5 jno 000002AC 196 000002a7 call 682F3C1A 197 000002ac mov eax,dword ptr [ebp-24h] 198 000002af cmp eax,dword ptr [ebp+FFFFFF68h] 199 000002b5 jle 00000263 200 Console.WriteLine((DateTime.Now - start).TotalMilliseconds) 201 000002b7 lea ecx,[ebp+FFFFFF18h] 202 000002bd call 6678EAC8 203 000002c2 lea eax,[ebp+FFFFFF18h] 204 000002c8 sub esp,8 205 000002cb movq xmm0,mmword ptr [eax] 206 000002cf movq mmword ptr [esp],xmm0 207 000002d4 lea eax,[ebp-18h] 208 000002d7 sub esp,8 209 000002da movq xmm0,mmword ptr [eax] 210 000002de movq mmword ptr [esp],xmm0 211 000002e3 lea ecx,[ebp+FFFFFF10h] 212 000002e9 call 6678A950 213 000002ee lea edi,[ebp-30h] 214 000002f1 lea esi,[ebp+FFFFFF10h] 215 000002f7 movq xmm0,mmword ptr [esi] 216 000002fb movq mmword ptr [edi],xmm0 217 000002ff lea ecx,[ebp-30h] 218 00000302 call 6678DD38 219 00000307 fstp qword ptr [ebp+FFFFFF08h] 220 0000030d fld qword ptr [ebp+FFFFFF08h] 221 00000313 sub esp,8 222 00000316 fstp qword ptr [esp] 223 00000319 call 66E72E20 224 225 Console.WriteLine("--------------------------------") 226 0000031e mov ecx,dword ptr ds:[033C219Ch] 227 00000324 call 6682AAB8 228 'Next 229 End Sub 230 00000329 nop 231 0000032a lea esp,[ebp-8] 232 0000032d pop esi 233 0000032e pop edi 234 0000032f pop ebp 235 00000330 ret
对比不同点(If-Else || If(Express,SelecetValue1,SelectValue2) || IIf(Express,SelecetValue1,SelectValue2):
红色方框内的行数,影响到运行时间。
看后我们发现,If-Else 与 If(Express,SelectValue1,SelectValue2) 实现的IL代码几乎完全一样( If(Express,SelectValue1,SelectValue2) IL中虽然多执行了两步操作,但是仔细看你会发现只不过是进行了多余操作)。
那么我们在执行过程时,为什么If-Else的时间略比If(Express,SelectValue1,SelectValue2)的时间大呢? 那是因为If-Else里面多了nop 指令,如果没它,If-Else 比 If(Express,SelectValue1,SelectValue2) 快。
至于 IIf(Express,SelectValue1,SelectValue2) 那是因为里面多进行了两步call 指令,这两个过程是执行内存别处指令,执行完之后再跳转回执行下一条指令(应该是Iff有很多判断,比较复杂吧?!我没用有仔细查看内存)。
帮助信息(参阅 IL指令汇总):
dword ptr[ebp-0Ch] : 取内存地址ebp-0Ch中的数据,地址ebp-0Ch中保存的是Integer i
cmp dword ptr[ebp-0Ch] , 0 : 比较 i 和 0 【对两数进行相减,进行比较,不将两数的差放入第一个操作数,影响标志寄存器,个人认为应该影响零标识(ZF)和符号标识(SF),具体的请搜索下标志寄存器】
jne 000000d3 : ZF=0 , 跳转至 000000d3 (ZF是零标识,若运算结果为零则ZF=1,否则ZF=0)
mov eax , dword ptr[ebp+FFFFFF04h] : 将操作数dword ptr[ebp+FFFFFF04h]送入eax寄存器 , 这个是什么玩意呢? 此句中的dword ptr[ebp+FFFFFF04h] 指向我们自定义的字符串
jmp 000000DF : 强制跳转至 000000DF
je 000001A1 : ZF=1,跳转至 000001A1 (参考jne)
sete cl : 取标志寄存器中ZF的值, 放到cl中
call 55EC3238 : 调至55EC3238执行指令
movzx ecx , cl : ecx 高位8~32位强制为0
nop :本指令不产生任何结果,仅消耗几个时钟周期的时间,接着执行后续指令,常用于程序的延时等