2012-02-16 16 views
5

Hace poco estuve leyendo this article de Dave Detlefs en la que presenta algunos casos en los que CLR realiza la eliminación de comprobación de límites de matriz. Decidí probar esto por mí mismo, así que hice lo siguiente:Array Bounds Check Elimination en el CLR?

  • abierto Visual Studio 2010 Ultimate SP1
  • Creado un nuevo proyecto de C# del tipo de aplicación de consola (con el objetivo .NET 4 Client Profile por defecto)
  • añadido el siguiente código (todos los sub-métodos se toman directamente de la 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]; 
        } 
    } 
    
  • conmutada al modo de liberación; verificó que "Código Optimizar" se comprueba en las opciones de generación

  • añadido un punto de interrupción a cada acceso a la matriz, se inició la depuración (F5) y abrió la ventana Desensamblaje

Así que aquí está el Desensamblaje de a [i] = yo; 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 

El cmp/JB/llamada es la comprobación de límites, en realidad forzando la llamada a ser ejecutado emite una IndexOutOfRangeException.

Lo mismo para todos los accesos a la 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.

+10

Cuando dice "inició la depuración", supongo que lanzó la aplicación * con el depurador adjunto * desde el entorno de Visual Studio. En ese caso, debe asegurarse de que la compilación JIT esté activada porque no está predeterminada. El compilador JIT es el que realiza esta optimización, no el compilador C#. –

+0

¿Qué espera que suceda si la verificación de límites está deshabilitada? En general, esta es una característica que la gente espera tener cuando usa un lenguaje administrado como C#. –

+1

La forma más fácil de garantizar que la optimización está realmente habilitada para iniciar la aplicación sin depuración y luego adjuntar depurador a la misma. – svick

Respuesta

12

Gracias a un comentario por Cody gris, he conseguido responder a mi propia pregunta:

Por defecto, optimizaciones JIT se desactivan cuando la depuración. Para solucionar esto, puede ir a Depurar -> Opciones y configuraciones -> Depuración -> General, y desmarque tanto "Activar solo mi código" y "Suprimir la optimización de JIT en la carga del módulo".

Véase también http://msdn.microsoft.com/en-us/library/ms241594.aspx

Con la optimización activada, el comprobación de límites se eliminan como se anuncia.

Lo dejo aquí para fines de documentación.