我最近在阅读Dave Detlefs的this article,他在其中介绍了CLR执行数组边界检查消除的几种情况。我决定自己对此进行测试,因此我执行了以下操作:
class Program {
static void Main(string[] args) {
int[] array = new int[30];
Test_SimpleAscend(array);
Test_SimpleRedundant(array, 3);
foreach (int i in array) {
Console.WriteLine(i);
}
}
static void Test_SimpleAscend(int[] a) {
for (int i = 0; i < a.Length; i++)
a[i] = i;
}
static void Test_SimpleRedundant(int[] a, int i) {
int k = a[i];
k = k + a[i];
}
}
这是a [i] = i;的反汇编。在Test_SimpleAscend中:
a[i] = i;
00000024 mov eax,dword ptr [ebp-4]
00000027 mov edx,dword ptr [ebp-8]
0000002a cmp eax,dword ptr [edx+4]
0000002d jb 00000034
0000002f call 64FD6E08
00000034 mov ecx,dword ptr [ebp-4]
00000037 mov dword ptr [edx+eax*4+8],ecx
cmp/jb/call是边界检查,实际上强制执行该调用将引发IndexOutOfRangeException。
对于所有阵列访问,包括Test_SimpleRedundant中的冗余访问,都是相同的。那么我的测试方法是否有问题,或者CLR实际上没有消除边界检查?我希望我是错的,如果是这样的话,我想知道如何才能真正消除数组边界检查。
最佳答案
感谢 Cody Gray 的评论,我设法回答了我自己的问题:
默认情况下,调试时禁用 JIT 优化。要解决此问题,可以转到调试 -> 选项和设置 -> 调试 -> 常规,然后取消选中“仅启用我的代码”和“在模块加载时抑制 JIT 优化”。
另见 https://docs.microsoft.com/en-us/visualstudio/debugger/jit-optimization-and-debugging
启用优化后,边界检查将如宣传的那样被删除。
出于文档目的,我将把它留在这里。
关于c# - CLR 中的数组边界检查消除?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9304726/