Udostępnij za pośrednictwem


Optymalizacja i debugowanie JIT

Jeśli próbujesz debugować kod, łatwiej jest zoptymalizować ten kod. Gdy kod jest zoptymalizowany, kompilator i środowisko uruchomieniowe wprowadza zmiany w emitowanym kodzie procesora CPU, dzięki czemu działa szybciej, ale ma mniej bezpośrednie mapowanie na oryginalny kod źródłowy. Jeśli mapowanie jest mniej bezpośrednie, debugery często nie mogą powiedzieć wartości zmiennych lokalnych, a kroki i punkty przerwania kodu mogą nie działać zgodnie z oczekiwaniami.

Uwaga

Aby uzyskać więcej informacji na temat debugowania JIT (Just In Time), przeczytaj tę dokumentację.

Jak działają optymalizacje na platformie .NET

Zwykle konfiguracja kompilacji wydania tworzy zoptymalizowany kod, a konfiguracja kompilacji debugowania nie. Właściwość Optimize MSBuild określa, czy kompilator ma zoptymalizować kod.

W ekosystemie platformy .NET kod jest zamieniany ze źródła na instrukcje procesora CPU w procesie dwuetapowym: najpierw kompilator języka C# konwertuje tekst wpisany na pośredni formularz binarny o nazwie MSIL i zapisuje kod MSIL w celu .dll plików. Później środowisko uruchomieniowe platformy .NET konwertuje ten zestaw MSIL na instrukcje dotyczące procesora CPU. Oba kroki można zoptymalizować w pewnym stopniu, ale drugi krok wykonywany przez środowisko uruchomieniowe platformy .NET wykonuje bardziej znaczące optymalizacje.

Opcja "Pomiń optymalizację JIT przy obciążeniu modułu (tylko zarządzana)"

Debuger uwidacznia opcję, która kontroluje, co się stanie, gdy biblioteka DLL skompilowana z włączonymi optymalizacjami jest ładowana wewnątrz procesu docelowego. Jeśli ta opcja nie jest zaznaczona (stan domyślny), to gdy środowisko uruchomieniowe platformy .NET kompiluje kod MSIL do kodu procesora CPU, pozostawia włączone optymalizacje. Jeśli opcja jest zaznaczona, debuger żąda wyłączenia optymalizacji.

Aby znaleźć opcję Pomiń optymalizację JIT przy obciążeniu modułu (tylko zarządzany), wybierz pozycję Opcje narzędzi>, a następnie wybierz stronę Ogólne w węźle Debugowanie.

Pomijanie optymalizacji JIT

Kiedy należy sprawdzić opcję "Pomiń optymalizację JIT"?

Zaznacz tę opcję po pobraniu bibliotek DLL z innego źródła, takiego jak pakiet nuget, i chcesz debugować kod w tej biblioteki DLL. Aby pomijanie działało, należy również znaleźć plik symbolu (.pdb) dla tej biblioteki DLL.

Jeśli interesuje Cię tylko debugowanie kodu tworzonego lokalnie, najlepiej pozostawić tę opcję niezaznaczoną, ponieważ w niektórych przypadkach włączenie tej opcji znacznie spowolni debugowanie. Istnieją dwie przyczyny tego spowolnienia:

  • Zoptymalizowany kod działa szybciej. Jeśli wyłączasz optymalizacje dla wielu kodu, wpływ na wydajność może się zwiększać.
  • Jeśli masz włączony tylko mój kod, debuger nawet nie spróbuje załadować symboli dla bibliotek DLL, które są zoptymalizowane. Znajdowanie symboli może zająć dużo czasu.

Ograniczenia opcji "Pomijanie optymalizacji JIT"

Istnieją dwie sytuacje, w których włączenie tej opcji NIE będzie działać:

  1. W sytuacjach, gdy dołączasz debuger do już uruchomionego procesu, ta opcja nie będzie miała wpływu na moduły, które zostały już załadowane w momencie dołączenia debugera.

  2. Ta opcja nie ma wpływu na biblioteki DLL, które zostały wstępnie skompilowane (lub ngen'ed) do kodu natywnego. Można jednak wyłączyć użycie wstępnie skompilowanego kodu, uruchamiając proces ze zmienną środowiskową "COMPlus_ReadyToRun" ustawioną na wartość "0". Spowoduje to, że środowisko uruchomieniowe platformy .NET Core wyłączy użycie wstępnie skompilowanych obrazów, zmuszając środowisko uruchomieniowe do kompilowania kodu platformy JIT.

    Jeśli używasz programu .NET Framework, dodaj zmienną środowiskową "COMPlus_ZapDisable" i ustaw ją na wartość "1".

Ustaw"COMPlus_ReadyToRun": "0", dodając go do każdego profilu w pliku Properties\launch Ustawienia.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"
    }
  }
}