JIT-оптимизация и отладка
Проще всего выполнять отладку кода, когда он НЕ оптимизирован. Когда код оптимизирован, компилятор и среда выполнения вносят изменения в выпущенный код ЦП, поэтому он выполняется быстрее, но имеет не такое прямое сопоставление с начальным исходным кодом. Если сопоставление менее прямое, отладчикам часто не удается определить значения локальных переменных и пошаговое выполнение кода и точки останова могут не работать должным образом.
Примечание.
Дополнительные сведения о JIT-отладке см. в этой документации.
Принцип действия оптимизации в .NET
Как правило, конфигурация сборки "Выпуск" создает оптимизированный код, а конфигурация сборки "Отладка" — нет. Свойство MSBuild Optimize
определяет, нужно ли компилятору оптимизировать код.
В экосистеме .NET код преобразуется из исходного в инструкции ЦП в два этапа: сначала компилятор C# преобразует введенный текст в промежуточную двоичную форму, называемую MSIL, и записывает код MSIL в DLL-файлы. Затем среда выполнения .NET преобразует этот код MSIL в инструкции ЦП. Оба действия можно оптимизировать до некоторой степени, но второй шаг, выполняемый средой выполнения .NET, осуществляет более значительные оптимизации.
Параметр "Отключать JIT-оптимизацию при загрузке модуля (только управляемый код)"
Отладчик предоставляет параметр, который управляет тем, что происходит, когда библиотека DLL, скомпилированная с включенной оптимизацией, загружается внутри целевого процесса. Если этот флажок не установлен (состояние по умолчанию), то, когда среда выполнения .NET компилирует код MSIL в код CPU, оптимизация остается включенной. Если флажок установлен, отладчик запрашивает отключение оптимизации.
Чтобы найти параметр Отключать JIT-оптимизацию при загрузке модуля (только управляемый код), щелкните Сервис>Параметры, а затем выберите страницу Общие в узле Отладка.
Когда следует включить параметр "Отключать JIT-оптимизацию"?
Установите этот флажок, если вы скачали библиотеки DLL из другого источника, например пакета NuGet, и хотите отладить код в этой библиотеке DLL. Чтобы отключение вступило в силу, необходимо также найти файл символов (PDB) для этой библиотеки DLL.
Если вас интересует отладка только локально создаваемого кода, лучше оставить этот флажок снятым, так как в некоторых случаях включение этого параметра значительно замедляет отладку. Для этого имеются две причины.
- Оптимизированный код выполняется быстрее. Если вы отключаете оптимизацию для большей части кода, это может повлиять на производительность.
- Если включен только пользовательский код, отладчик даже не будет пытаться загружать символы для оптимизированных DLL. Поиск символов может занять много времени.
Ограничения для использования параметра "Отключать JIT-оптимизацию"
Существует две ситуации, когда включение этого параметра НЕ работает.
В ситуациях, когда вы присоединяете отладчик к уже выполняющемуся процессу, этот параметр не влияет на модули, которые уже были загружены во время подключения отладчика.
Этот параметр не влияет на библиотеки DLL, которые были предварительно скомпилированы (или ngen'ed) в машинном коде. Однако использование предварительно скомпилированного кода можно отключить, запустив процесс с переменной среды COMPlus_ReadyToRun со значением 0. Это укажет среде выполнения .NET Core на необходимость отключения использования предварительно скомпилированных образов и приведет к принудительной JIT-компиляции кода платформы.
Если вы используете .NET Framework, добавьте переменную среды COMPlus_ZapDisable и задайте для нее значение 1.
Задайте "COMPlus_ReadyToRun": "0"
, добавив его в каждый профиль в файле 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"
}
}
}