我最近閱讀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實際上並沒有消除邊界檢查?我希望我錯了,如果是的話,我想知道我是如何真正獲得數組邊界檢查消除。
當你說「開始調試」時,我假設你從Visual Studio環境啓動了附帶*的調試器的應用程序*。在這種情況下,您需要確保JIT編譯已啓用,因爲它不是默認值。 JIT編譯器是執行此優化的編譯器,而不是C#編譯器。 – 2012-02-16 02:36:32
如果邊界檢查被禁用,你預期會發生什麼?這通常是人們在使用C#等託管語言時所期望的功能。 – 2012-02-16 02:42:56
確保優化的最簡單方法實際上是啓用應用程序而無需調試,然後將調試器附加到它。 – svick 2012-02-16 02:42:59