Codegenerierung in der Profilerstellungs-API
In diesem Thema werden der Übergang von MSIL (Microsoft Intermediate Language)-Code in systemeigenen Code sowie die Steuerung der Codegenerierung durch Profiler erläutert.
Automatische und manuelle Codegenerierung
Es gibt zwei Möglichkeiten, die MSIL in einer .NET Framework-Assembly in systemeigenem Code zu kompilieren:
Manuelle Kompilierung: Das Tool Native Image Generator (NGen.exe) kann zum Erstellen eines systemeigenen Abbilds verwendet werden.
Automatische Kompilierung: Die Common Language Runtime (CLR) kann zur Laufzeit eine JIT (Just-In-Time)-Kompilierung durchführen.
Sowohl NGen.exe als auch der JIT-Compiler stellen Flags zur Steuerung der Codegenerierung bereit.
Wenn eine Assembly geladen wird, sucht die CLR zuerst nach einem systemeigenen Abbild für die Assembly. Wenn die CLR kein systemeigenes Abbild mit den richtigen Flags für die Codegenerierung finden kann, wendet sie die JIT-Kompilierung für die Funktionen in der Assembly dann an, wenn sie zur Laufzeit benötigt werden. Auch wenn ein systemeigenes Abbild gefunden und geladen wird, wendet die CLR die JIT-Kompilierung für einige Funktionen in der Assembly an.
Profilersteuerung über Codegenerierung
Der Profiler verwendet die in der folgenden Tabelle aufgeführten Flags zur Steuerungscodegenerierung.
Flag |
Wirkung |
---|---|
COR_PRF_USE_PROFILE_IMAGES |
(Erfordert .NET Framework, Version 2.0.) Bewirkt, dass die Suche nach systemeigenen Abbildern nach durch Profiler verbesserten Abbildern sucht (ngen /profile). Wenn bei der Suche kein vom Profiler verbessertes systemeigenes Abbild für eine bestimmte Assembly gefunden wird, wendet die CLR stattdessen bei Bedarf eine JIT-Kompilierung für die Methoden in der Assembly an. Hat keine Auswirkungen auf JIT-kompilierten Code. |
COR_PRF_DISABLE_INLINING |
Hat keine Auswirkungen auf die Suche nach dem systemeigenen Abbild. Deaktiviert bei der JIT-Kompilierung das Inlining. Alle anderen Optimierungen bleiben wirksam. |
COR_PRF_DISABLE_OPTIMIZATIONS |
Hat keine Auswirkungen auf die Suche nach dem systemeigenen Abbild. Deaktiviert bei der JIT-Kompilierung alle Optimierungen, einschließlich Inlining. |
COR_PRF_MONITOR_ENTERLEAVE |
Bewirkt, dass die Suche nach systemeigenen Abbildern nach durch Profiler verbesserten Abbildern sucht (ngen /profile). Fügt bei der JIT-Kompilierung enter/leave-Hooks in den generierten Code ein. |
COR_PRF_MONITOR_CODE_TRANSITIONS |
Bewirkt, dass die Suche nach systemeigenen Abbildern nach durch Profiler verbesserten Abbildern sucht (ngen /profile). Fügt bei der JIT-Kompilierung Hooks in verwaltete/nicht verwaltete Übergangspunkte ein. |
Profiler und systemeigene Abbilder
Wenn NGen.exe ein systemeigenes Abbild erstellt, wird hierbei ein Großteil der Arbeit durchgeführt, die normalerweise von der CLR zur Laufzeit erledigt wird (z. B. das Laden von Klassen und die Funktionskompilierung). Daher werden, wenn die Arbeit von NGen durchgeführt wurde, die folgenden Profilerrückrufe nicht zur Laufzeit erhalten:
Durch Profiler verbesserte systemeigene Abbilder
Bei der Erstellung eines systemeigenen Abbilds mit NGen.exe wird eine Reihe von Flags für die Codegenerierung aktiviert, mit der sich ein Profil für das Abbild einfacher erstellen lässt:
In den Code werden enter/leave-Hooks eingefügt.
In den Code werden Hooks für verwaltete/nicht verwaltete Übergänge eingefügt.
Die ICorProfilerCallback::JITCachedFunctionSearchStarted-Benachrichtigung und die ICorProfilerCallback::JITCachedFunctionSearchFinished-Benachrichtigung werden ausgegeben, wenn die einzelnen Funktionen des systemeigenen Abbilds zum ersten Mal aufgerufen werden.
Die ICorProfilerCallback::ClassLoadStarted-Benachrichtigung und die ICorProfilerCallback::ClassLoadFinished-Benachrichtigung werden ausgegeben, wenn die einzelnen Klassen im systemeigenen Abbild zum ersten Mal verwendet werden.
Überlegungen zur Leistung
Die Entscheidung, welche Methode Sie zum Erstellen von Profilen für die mit NGen generierten Anwendungen verwenden, hängt von zwei Überlegungen ab: Welche Daten sollen abgerufen werden, und welche Auswirkungen haben die eingebetteten Profilerstellungshooks auf die Anwendung?
Wie bereits in diesem Thema erläutert, gibt es zwei grundlegende NGen-Profilerstellungsszenarios:
Normale systemeigene Abbilder (NGen-generierte Abbilder ohne Profilerstellungshooks): Diese Bilder verursachen keinen Aufwand bei der Profilerstellung. Die Rückrufe zum Laden/Entladen der Klasse stehen für normale systemeigene Abbilder jedoch nicht zur Verfügung. In dieser Situation muss ein Profiler, der keine durch Profiler verbesserte systemeigene Abbilder anfordern will, Daten über FunctionIDs oder ClassIDs erfassen, wenn er auf diese IDs trifft. So trifft ein Samplingprofiler beispielsweise nicht auf eine FunctionID, wenn die FunctionID zunächst mit der JIT-Methode kompiliert oder aus einem NGen-generierten Abbild geladen wird, da die Rückrufe zum Laden/Entladen der Klasse nicht für normale NGen-generierte Abbilder ausgegeben werden. Der Profiler trifft später auf die FunctionID, wenn beim Sampling gezeigt wird, dass der Prozess bei einem Anweisungszeiger (Instruction Pointer, IP) im Text des kompilierten Codes der Funktion ausgeführt wurde. In diesem Fall kann der Profiler Informationen über die Funktion beim Sampling abrufen, oder er kann die FunctionID bzw. das damit verknüpfte Metadatentoken für eine noch spätere Abfrage protokollieren. Daher fordert der Profiler Informationen über die FunctionID oder die ClassID nur im letztmöglichen Moment an (wenn erkannt wird, dass die ID tatsächlich verwendet wird) und nicht früher, wenn die ID erstmalig erzeugt wird.
Durch Profiler verbesserte systemeigene Abbilder (NGen-generierte Abbilder mit eingebetteten Profilerstellungshooks): Diese Abbilder sind größer und unterscheiden sich deutlich von normalen Abbildern. Außerdem ist das Verhalten der Anwendung möglicherweise anders, wenn sie Profilerhooks einschließt. Sie sollten durch Profiler verbesserte Abbilder daher nur dann verwenden, wenn die zu erwartenden Auswirkungen auf die Leistung und das Verhalten (Mehraufwand) akzeptabel sind.