JIT-Optimierung und -Debuggen

Wenn Sie versuchen, Code zu debuggen, ist es einfacher, wenn der Code NICHT optimiert ist. Wenn der Code optimiert ist, nehmen der Compiler und die Runtime Änderungen am ausgegebenen CPU-Code vor, sodass er schneller ausgeführt wird, aber eine geringere direkte Zuordnung zum ursprünglichen Quellcode aufweist. Wenn die Zuordnung weniger direkt ist, können Debugger häufig nicht den Wert lokaler Variablen erkennen, und Codeschritte und Breakpoints funktionieren möglicherweise nicht wie erwartet.

Hinweis

Weitere Informationen zum JIT-Debuggen (Just-in-Time) finden Sie in dieser Dokumentation.

Funktionsweise von Optimierungen in .NET

Im Gegensatz zur Buildkonfiguration „Debuggen“ erstellt die Buildkonfiguration „Release“ in der Regel optimierten Code. Die MSBuild-Eigenschaft Optimize steuert, ob der Compiler aufgefordert wird, Code zu optimieren.

Im .NET-Ökosystem wird Code in einem zweistufigen Prozess von der Quelle in CPU-Anweisungen umgewandelt: Zuerst konvertiert der C#-Compiler den eingegebenen Text in ein binäres Zwischenformat namens MSIL und schreibt dieses in DLL-Dateien. Später konvertiert die .NET-Runtime dieses MSIL-Format in CPU-Anweisungen. Beide Schritte sorgen in gewissem Maß für Optimierungen, aber der zweite Schritt, der von der .NET-Runtime ausgeführt wird, führt zu den signifikanteren Optimierungen.

Option „JIT-Optimierung beim Laden von Modulen unterdrücken (nur verwaltet)“

Der Debugger macht eine Option verfügbar, die steuert, was geschieht, wenn eine mit Optimierungen kompilierte DLL innerhalb des Zielprozesses geladen wird. Wenn diese Option deaktiviert ist (Standardzustand), werden die Optimierungen beim Kompilieren des MSIL-Codes in CPU-Code von der .NET-Runtime aktiviert. Wenn die Option aktiviert ist, wird vom Debugger angefordert, dass Optimierungen deaktiviert werden.

Klicken Sie auf Extras>Optionen und dann unter dem Knoten Debuggen auf die Seite Allgemein, um die Option JIT-Optimierung beim Laden von Modulen unterdrücken (nur verwaltet) zu finden.

JIT-Optimierung unterdrücken

Wann sollten Sie die Option „JIT-Optimierung unterdrücken“ aktivieren?

Aktivieren Sie diese Option, wenn Sie die DLLs aus einer anderen Quelle (z. B. einem NuGet-Paket) heruntergeladen haben und den Code in dieser DLL debuggen möchten. Damit die Unterdrückung funktioniert, müssen Sie auch die Symboldatei (PDB-Datei) für diese DLL finden.

Wenn Sie nur den Code debuggen möchten, den Sie lokal erstellen, empfiehlt es sich, diese Option nicht zu deaktivieren. In manchen Fällen wird das Debuggen durch Aktivieren dieser Option erheblich verlangsamt. Es gibt zwei Gründe für diese Verlangsamung:

  • Optimierter Code wird schneller ausgeführt. Wenn Sie die Optimierungen für Code deaktivieren, kann sich dies auf die Leistung auswirken.
  • Wenn die Option „Nur eigenen Code“ aktiviert ist, versucht der Debugger nicht einmal, Symbole für optimierte DLLs zu laden. Die Suche nach Symbolen kann viel Zeit in Anspruch nehmen.

Einschränkungen der Option „JIT-Optimierung unterdrücken“

Es gibt zwei Situationen, in denen das Aktivieren dieser Option NICHT funktioniert:

  1. In Situationen, in denen der Debugger an einen bereits laufenden Prozess angefügt wird, hat diese Option keine Auswirkungen auf Module, die zum Zeitpunkt der Anfügung des Debuggers bereits geladen wurden.

  2. Diese Option hat keine Auswirkung auf DLLs, die in nativem Code vorkompiliert wurden (oder ngen'ed). Sie können jedoch die Verwendung von vorkompiliertem Code deaktivieren, indem Sie den Prozess mit der Umgebungsvariablen COMPlus_ReadyToRun auf 0 (null) festlegen. Dadurch wird der .NET Core-Runtime mitgeteilt, die Verwendung von vorkompilierten Images zu deaktivieren. Auf diese Weise wird die Runtime zur JIT-Kompilierung von Frameworkcode gezwungen.

    Wenn Sie auf .NET Framework abzielen, fügen Sie die Umgebungsvariable 'COMPlus_ZapDisable' hinzu, und legen Sie sie auf '1' fest.

Legen Sie die Variable "COMPlus_ReadyToRun": "0" fest, indem Sie sie jedem Profil in der Datei Properties\launchSettings.json hinzufügen:

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