CLR 中的数组边界检查消除?

发布于 2025-01-06 05:54:45 字数 1486 浏览 1 评论 0原文

我最近正在阅读 Dave Detlefs 的这篇文章,其中介绍了 CLR 执行数组边界检查消除的一些情况。我决定自己测试一下,因此我执行了以下操作:

  • 打开 Visual Studio 2010 Ultimate SP1
  • 创建了一个控制台应用程序类型的新 C# 项目(默认针对 .NET 4 Client Profile)
  • 添加了以下代码(所有子方法)直接摘自文章):

    类程序{
        静态无效主(字符串[]参数){
            int[] 数组 = 新 int[30];
            Test_SimpleAscend(数组);
            Test_SimpleRedundant(数组, 3);
    
            foreach(数组中的 int i){
                Console.WriteLine(i);
            }
        }
    
        静态无效 Test_SimpleAscend(int[] a) {
            for (int i = 0; i < a.Length; i++)
                a[i] = i;
        }
    
        静态无效 Test_SimpleRedundant(int[] a, int i) {
            int k = a[i];
            k = k + a[i];
        }
    }
    
  • 切换到Release模式;验证在构建选项中选中了“优化代码”

  • 向每个数组访问添加了一个断点,开始调试(F5)并打开反汇编窗口

所以这是 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 实际上并没有消除边界检查?我希望我错了,如果是这样,我想知道如何真正获得数组边界检查消除。

I was recently reading this article by Dave Detlefs in which he presents a few cases where the CLR performs array bounds check elimination. I decided to test this myself, so I did the following:

  • Opened Visual Studio 2010 Ultimate SP1
  • Created a new C# project of type Console Application (targeting .NET 4 Client Profile by default)
  • Added the following code (all sub-methods are taken directly from the article):

    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];
        }
    }
    
  • Switched to Release mode; verified that "Optimize Code" is checked in the Build options

  • Added a breakpoint to each array access, started debugging (F5) and opened the Dissassembly window

So here's the dissassembly for a[i] = i; in 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 

The cmp/jb/call is bounds checking, actually forcing the call to be executed throws an IndexOutOfRangeException.

Same thing for all array accesses, including the redundant access in Test_SimpleRedundant. So is there something wrong with my testing methodology, or the CLR doesn't actually eliminate bounds checking? I hope I'm wrong and if so I'd like to know how I can really get array bounds checking elimination.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

温暖的光 2025-01-13 05:54:45

感谢 Cody Gray 的评论,我成功回答了自己的问题:

默认情况下,调试时会禁用 JIT 优化。要解决此问题,可以转到“调试”->“调试”。选项和设置 ->调试->常规,然后取消选中“仅启用我的代码”和“抑制模块加载时的 JIT 优化”。

另请参阅 https://learn.microsoft.com/ en-us/visualstudio/debugger/jit-optimization-and-debugging

启用优化后,边界检查将按广告删除。

我将把它留在这里用于文档目的。

Thanks to a comment by Cody Gray, I've managed to answer my own question:

By default, JIT Optimizations are disabled when debugging. To fix this, one can go to Debug -> Options and Settings -> Debugging -> General, and uncheck both "Enable Just My Code" and "Suppress JIT Optimization on module load".

Also see https://learn.microsoft.com/en-us/visualstudio/debugger/jit-optimization-and-debugging

With optimization enabled, the bounds check are removed as advertised.

I'll leave this here for documentation purposes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文