Поделиться через


Оптимизация JIT и отладка

Если вы пытаетесь отладить код, это проще, если этот код не оптимизирован. При оптимизации кода компилятор и среда выполнения вносят изменения в создаваемый код центрального процессора, чтобы он выполнялся быстрее, но имеет менее прямое сопоставление с исходным кодом. Если сопоставление менее прямое, отладчики часто не могут сообщить вам значение локальных переменных, а пошаговое выполнение кода и точки останова могут не работать так, как вы ожидаете.

Замечание

Для получения дополнительной информации об отладке JIT (Just In Time) прочитайте эту документацию.

Как работают оптимизации в .NET

Обычно конфигурация сборки Релиз создает оптимизированный код, а конфигурация сборки Отладка — нет. Свойство Optimize MSBuild определяет, будет ли компилятор оптимизировать код.

В экосистеме .NET код преобразуется из источника в инструкции ЦП в двухфакторном процессе: сначала компилятор C# преобразует текст, который вы вводите в промежуточную двоичную форму MSIL, и записывает MSIL в .dll файлы. Позже среда выполнения .NET преобразует этот MSIL в инструкции ЦП. Оба шага могут оптимизироваться до некоторой степени, но второй шаг, выполняемый средой выполнения .NET, выполняет более значительные оптимизации.

Параметр "Подавление оптимизации JIT во время загрузки модуля (только для управляемого кода)"

Отладчик предоставляет параметр, который управляет тем, что происходит, когда библиотека DLL, скомпилированная с включенными оптимизацией, загружается внутри целевого процесса. Если этот параметр снят (состояние по умолчанию), то когда среда выполнения .NET компилирует код MSIL в код ЦП, он оставляет включенные оптимизации. Если установлен флажок, отладчик запрашивает отключение оптимизации.

Чтобы найти параметр "Отключить оптимизацию JIT" для загрузки модуля (только для управляемых), выберите"Параметры>" и выберите страницу "Общие" в узле отладки.

Подавление JIT-оптимизации

Когда следует проверить параметр "Подавление оптимизации JIT"?

Проверьте этот параметр при скачивании библиотек DLL из другого источника, например пакета nuget, и вы хотите отлаживать код в этой библиотеке DLL. Чтобы подавление работало, необходимо также найти файл символа (.pdb) для этой библиотеки DLL.

Если вы заинтересованы только в отладке кода, который вы создаете локально, рекомендуется оставить этот параметр без флажка, так как в некоторых случаях включение этого параметра значительно замедлит отладку. Существует две причины для этого замедления:

  • Оптимизированный код выполняется быстрее. Если вы отключаете оптимизацию для большого объема кода, это может негативно влиять на производительность.
  • Если включена функция Just My Code, отладчик даже не попытается загрузить символы для оптимизированных DLL. Поиск символов может занять много времени.

Ограничения параметра "Подавление оптимизации JIT"

Существует две ситуации, когда включение этого параметра не будет работать:

  1. В ситуациях, когда вы подключаете отладчик к уже запущенному процессу, этот параметр не влияет на модули, которые уже загружены в момент подключения отладчика.

  2. Этот параметр не влияет на библиотеки DLL, которые были предварительно скомпилированы (или ngen'ed) в машинном коде. Однако можно отключить использование предварительно скомпилированного кода, запуская процесс с переменной среды "COMPlus_ReadyToRun", для которой задано значение "0". Это сообщит среде выполнения .NET Core отключить использование предварительно скомпилированных образов, вынуждая среду выполнения выполнять JIT-компиляцию кода фреймворка.

    Если вы нацелены на .NET Framework, добавьте переменную среды "COMPlus_ZapDisable" и задайте для нее значение "1".

Задайте "COMPlus_ReadyToRun": "0", добавив его в каждый профиль в разделе Свойства\launchSettings.js файла:

{
  "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"
    }
  }
}