Optimización y depuración JIT

Si intenta depurar código, resulta más fácil cuando ese código no está optimizado. Cuando se optimiza el código, el compilador y el tiempo de ejecución realizan cambios en el código de CPU emitido para que se ejecute más rápido, pero tiene una asignación menos directa al código fuente original. Si la asignación es menos directa, los depuradores a menudo no pueden indicarle el valor de las variables locales, y es posible que los puntos de interrupción y la ejecución de código no funcionen como se espera.

Nota

Para más información sobre la depuración JIT (Just-In-Time), lea esta documentación.

Funcionamiento de las optimizaciones en .NET

Normalmente, la configuración de compilación de versión crea código optimizado y la configuración de compilación de depuración no. La propiedad Optimize de MSBuild controla si se indica al compilador que optimice el código.

En el ecosistema de .NET, el código se convierte de las instrucciones de origen a las de la CPU en un proceso de dos pasos: en primer lugar, el compilador de C# convierte el texto que se escribe a un formato binario intermedio denominado MSIL y escribe el MSIL en los archivos .dll. Después, .NET Runtime convierte este MSIL en instrucciones de CPU. Ambos pasos se pueden optimizar hasta cierto punto, pero el segundo paso que .NET Runtime realiza lleva a cabo las optimizaciones más significativas.

Opción "Suprimir optimización JIT al cargar el módulo (solo administrado)"

El depurador expone una opción que controla lo que ocurre cuando un archivo DLL que se compila con optimizaciones habilitadas se carga dentro del proceso de destino. Si esta opción está desactivada (el estado predeterminado), cuando .NET Runtime compila el código MSIL en el código de CPU, deja las optimizaciones habilitadas. Si la opción está activada, el depurador solicita que se deshabiliten las optimizaciones.

Para buscar la opción Suprimir optimización JIT al cargar el módulo (solo administrado) , seleccione Herramientas>Opciones y luego la página General del nodo Depuración.

Suprimir optimización JIT

¿Cuándo se debe activar la opción "Suprimir optimización JIT"?

Active esta opción si descargó los archivos DLL de otro origen, como un paquete NuGet, y quiere depurar el código en este archivo DLL. Para que la supresión funcione, debe buscar también el archivo de símbolos (.pdb) para este archivo DLL.

Si solo le interesa depurar el código que está compilando localmente, es mejor dejar esta opción desactivada, ya que, en algunos casos, la habilitación de esta opción ralentizará considerablemente la depuración. Hay dos motivos para esta ralentización:

  • El código optimizado se ejecuta más rápido. Si va a desactivar las optimizaciones de gran cantidad de código, el impacto en el rendimiento puede ser mayor.
  • Si ha habilitado Solo mi código, el depurador ni siquiera intentará cargar símbolos para los archivos DLL que estén optimizados. La búsqueda de símbolos puede tardar mucho.

Limitaciones de la opción "Suprimir optimización JIT"

Hay dos situaciones en las que la activación de esta opción no funcionará:

  1. En situaciones en las que se asocia el depurador a un proceso ya en ejecución, esta opción no tendrá ningún efecto sobre los módulos que ya estaban cargados el momento en que se asoció el depurador.

  2. Esta opción no tiene ningún efecto en los archivos DLL que se han precompiladoen el código nativo. Aunque se puede deshabilitar el uso de código precompilado iniciando el proceso con la variable de entorno "COMPlus_ReadyToRun" establecida en "0" . Esto le indicará .NET Core Runtime que deshabilite el uso de imágenes precompiladas, que obliga al runtime a compilar código de marco JIT.

    Si tiene como destino .NET Framework, añada la variable de entorno COMPlus_ZapDisable y establézcala en to 1.

Establezca "COMPlus_ReadyToRun": "0" añadiéndolo a cada perfil en el archivo Properties\launchSettings.json:

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:59694/",
      "sslPort": 44320
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "COMPlus_ReadyToRun": "0"
      }
    },
    "HttpLoggingSample": {
      "commandName": "Project",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "COMPlus_ReadyToRun": "0"
      },
      "applicationUrl": "https://localhost:5001;http://localhost:5000"
    }
  }
}