c# arrays optimization clr bounds-check-elimination

c# - Array Bounds Comprobar la eliminación en el CLR?



arrays optimization (1)

Hace poco estuve leyendo este artículo de Dave Detlefs en el que presenta algunos casos en los que CLR realiza la eliminación de verificación de límites de matriz. Decidí probarlo yo mismo, así que hice lo siguiente:

  • Abrió Visual Studio 2010 Ultimate SP1
  • Se creó un nuevo proyecto de C # de tipo Aplicación de consola (orientación .NET 4 Client Profile de forma predeterminada)
  • Se agregó el siguiente código (todos los submétodos se toman directamente del artículo):

    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]; } }

  • Cambiado al modo de liberación; verificó que "Optimizar código" esté marcado en las opciones de compilación

  • Se agregó un punto de interrupción a cada acceso de matriz, se comenzó a depurar (F5) y se abrió la ventana de Disassembly

Así que aquí está el desmontaje para un [i] = i; en 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

La llamada cmp / jb / es comprobación de límites, lo que obliga a ejecutar la llamada arroja una excepción IndexOutOfRangeException.

Lo mismo para todos los accesos de matriz, incluido el acceso redundante en Test_SimpleRedundant. Entonces, ¿hay algo mal con mi metodología de prueba, o el CLR no elimina la verificación de límites? Espero estar equivocado y, de ser así, me gustaría saber cómo puedo obtener la eliminación de los límites de la matriz.


Gracias a un comentario de Cody Gray, he logrado responder mi propia pregunta:

De forma predeterminada, las optimizaciones de JIT están deshabilitadas cuando se depura. Para solucionar esto, puede ir a Depurar -> Opciones y Configuraciones -> Depuración -> General, y desmarque "Habilitar solo mi código" y "Suprimir la optimización de JIT en la carga del módulo".

También vea http://msdn.microsoft.com/en-us/library/ms241594.aspx

Con la optimización habilitada, la verificación de límites se elimina según lo anunciado.

Lo dejaré aquí para fines de documentación.