2012-02-16 27 views
5

我最近閱讀Dave Detlefs的this article,其中他介紹了CLR執行數組邊界檢查消除的一些情況。我決定把這個測試自己,所以我做了以下內容:CLR中的數組邊界檢查消除?

  • 開業的Visual Studio 2010旗艦版SP1
  • 創建類型的新的C#項目控制檯應用程序(目標默認.NET 4客戶端配置文件)
  • 添加以下代碼(所有子方法直接取自文章):

    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]; 
        } 
    } 
    
  • 切換到釋放模式;驗證了「優化代碼」的編譯選項

  • 新增斷點每個數組訪問,開始調試(F5)被選中,打開Dissassembly窗口

所以這裏的dissassembly A [1] =一世;在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 /調用是的邊界檢查,竟迫使通話將被執行拋出IndexOutOfRangeException。

對所有數組訪問都是一樣的,包括Test_SimpleRedundant中的冗餘訪問。那麼,我的測試方法有什麼問題,或者CLR實際上並沒有消除邊界檢查?我希望我錯了,如果是的話,我想知道我是如何真正獲得數組邊界檢查消除。

+10

當你說「開始調試」時,我假設你從Visual Studio環境啓動了附帶*的調試器的應用程序*。在這種情況下,您需要確保JIT編譯已啓用,因爲它不是默認值。 JIT編譯器是執行此優化的編譯器,而不是C#編譯器。 – 2012-02-16 02:36:32

+0

如果邊界檢查被禁用,你預期會發生什麼?這通常是人們在使用C#等託管語言時所期望的功能。 – 2012-02-16 02:42:56

+1

確保優化的最簡單方法實際上是啓用應用程序而無需調試,然後將調試器附加到它。 – svick 2012-02-16 02:42:59

回答

12

多虧了科迪灰色評論,我已經成功地回答我的問題:

默認情況下,在調試時JIT優化被禁用。要解決這個問題,可以進入調試 - >選項和設置 - >調試 - >常規,並取消勾選「啓用我的代碼」和「在模塊加載時抑制JIT優化」。

另見http://msdn.microsoft.com/en-us/library/ms241594.aspx

隨着優化啓用,爲標榜的範圍檢查被刪除。

我會在此處將其留作文檔目的。