我正在使用VB.NET 2010编写一个计算密集型程序,希望优化速度。我发现,如果将操作的结果分配给类级变量,运算符AndAlso
和OrElse
的速度异常缓慢。例如,当执行以下语句时:
a = _b AndAlso _c
_a = a
在编译后的可执行文件中,这两个单语句之间需要大约6个机器周期。
_a = _b AndAlso _c
执行这个语句需要大约80个机器周期。在这里,_a
、_b
和_c
是Form1
的私有布尔变量,而相关语句位于Form1
的实例过程中,其中a
是一个局部布尔变量。
我找不到这个单独语句为什么要花费如此长的时间。我使用NetReflector进行了探索,一直到CIL代码层面, 代码看起来很好:
Instruction Explanation Stack
00: ldarg.0 Push Me (ref to current inst of Form1) Me
01: ldarg.0 Push Me Me, Me
02: ldfld bool Form1::_b Pop Me, read _b and push it _b, Me
07: brfalse.s 11 Pop _b; if false, branch to 11 Me
09: ldarg.0 (_b true) Push Me Me, Me
0a: ldfld bool Form1::_c (_b true) Pop Me, read _c and push it _c, Me
0f: brtrue.s 14 (_b true) Pop _c; if true, branch to 14 Me
11: ldc.i4.0 (_b, _c not both true) Push result 0 result, Me
12: br.s 15 Jump unconditionally to 15 result, Me
-----
14: ldc.i4.1 (_b, _c both true) Push result 1 result, Me
15: stfld bool Form1::_a Pop result and Me; write result to _a (empty)
1a:
有人可以解释一下为什么语句_a = _b AndAlso _c
需要80个机器周期,而不是预测的5个或者更少吗?
我正在使用Windows XP,.NET 4.0和Visual Studio Express 2010。我用自己编写的一个比较简陋的代码片段来测量时间,该片段基本上使用Stopwatch对象计时一个包含代码的For-Next循环,循环中包含1000次迭代,并将其与一个空的For-Next循环进行比较;在两个循环中都包含了一个无用的指令来浪费一些周期并防止处理器停顿。这种方法对我来说足够粗略但够用。
And
会同时评估两侧。 - TyCobb