Glengamoi (Forum) · AspHeute · .NET Heute (RSS-Suche) · AspxFiles (Wiki) · .NET Blogs

.NET auf Warp 9 beschleunigen: Ngen

Geschrieben von: Christian Holm
Kategorie: .NET Allgemein

This printed page brought to you by AlphaSierraPapa

Das Ngen (Native Image Generator) Tool, welches dem .NET Framework SDK beiliegt, erstellt ein Abbild Ihrer Assembly in Maschinensprache im Global Assembly Cache (C#/VB.NET kompilieren zu IL, nicht Maschinensprache) . Dies beschleunigt die Ausführung gewaltig, da beim Erstaufruf der Assembly diese bereits in Maschinensprache vorliegt und nicht mehr durch den JIT Compiler dynamisch generiert werden muß.

Schon aus der Einleitung sollte ersichtlich sein, daß der Native Image Generator nichts mit irgendwelchen Eingeborenen oder deren Bildererstellung zu tun hat, obwohl der Name "verleitend" ist. Mit Native Code (Maschinensprache) ist eine Datei gemeint, die kompilierten Sourcecode enthält, der einem Prozessor-spezifischen Bytecode entspricht.

.NET Execution Process

Mit der Verwendung des .NET Frameworks hat sich einiges am Executionprozeß einer Anwendung geändert. Dieser sieht schematisch für eine .NET Applikation folgendermaßen aus:

Wenn der Sourcecode geschrieben ist, wird es Zeit, diesen zu kompilieren. Verwendet man C# oder VB.NET, so wird der Sourcecode nicht auf Maschinensprache kompiliert, sondern auf IL (Intermediate Language), die zusammen mit MetaData in die Assembly (EXE oder DLL zum Beispiel) geschrieben wird. Wichtig: es ist nicht verpflichtend für eine Programmiersprache auf IL zu kompilieren. Managed Code kann auch in Maschinensprache vorliegen (und das macht sich Ngen zunutze).

Die Kompilierung auf Native Code geschieht erst beim ersten Aufruf des Programms durch einen JIT-Compiler. Erst wenn diese Schritte erfolgreich abgeschlossen werden, wird Ihr Programm ausgeführt.

Hierbei sind wir schon beim Knackpunkt bzw. Flaschenhals. Für den Fall, daß Ihre .NET Applikation viele Assemblies umfaßt, müssen diese beim ersten Aufruf erst auf Native Code kompiliert werden. Bei vielen Assemblies kann dies sehr lange dauern. Natürlich werden die Assemblies nicht bei jedem Funktionsaufruf, sondern eben nur beim ersten kompiliert - solange sich an der Signatur der Assembly nichts ändert.

Vorhang auf für NGen

Mit dem Ngen Tool haben Sie nun die Möglichkeit diese Assemblies sofort auf Native Code zu kompilieren. Diese werden im GAC (Global Assembly Cache, \WinNT\assembly) als "Native Images" (bzw. Win 2000: "PreJit") geflaggt, damit der JIT-Compiler bzw. die Runtime weiß, daß diese Assemblies nicht mehr zu kompiliern sind, da diese schon als Native Code vorliegen.

Da die gesamte Arbeit vom Ngen Tool erledigt wird, brauchen Sie weder in Ihrem Sourcecode oder bei der Ausführung irgendwelche Anweisungen bzw. Switches hinzufügen - die Runtime inspiziert automatisch die Assemblies und entscheidet je nach gesetztem Flag was zu tun ist.

Jetzt werden Sie vielleicht zwei Fragen brennend interessieren:

Methoden die aus irgendwelchen Gründen nicht mit dem Ngen Tool auf Native Code kompiliert werden können, werden vom Tool nicht in das Native Image inkludiert. Wenn nun die Runtime diese Native Code Assembly bearbeitet, werden exkludierte Methoden trotz des "Native Images" Flag mit dem JIT Compiler kompiliert.

Die zweite Frage läßt sich nur unscharf beantworten. Unscharf deshalb, weil mehrere Faktoren die Startupphase einer Applikation beeinflussen können. Aber als Grundregel sollte gelten, daß das Vorkomplieren von Assemblies auf jeden Fall für clientseitige Applikationen und bei sehr vielen gleichzeitig zu ladenden Assemblies angewandt werden sollte.

NGen im Einsatz

Natürlich wollen wir nun dieses Tool ausprobieren und seine Handhabung kennenlernen. Dafür habe ich ein kleines Szenario vorbereitet, und etwas (einfachen) Sourcecode geschrieben. Der Sourcecode ist heute nur Mittel zum (Optimierungs)Zweck, deshalb entfällt seine Vorstellung. Der erste Schritt ist klarerweise die Kompilierung auf MSIL. Bei Erfolg wird eine DLL Assembly generiert, mit der wir nun weiterarbeiten werden.

Jetzt kommen wir zum interessanten Teil: die Erstellung eines Native Images aus der Assembly. Da das Ngen Tool im Moment eine Konsolenanwendung ist, öffnen wir zuallererst ein Kommandoprompt-Fenster (cmd.exe).

Hinweis: Wenn Sie das .NET Framework SDK installiert haben, haben Sie hoffentlich die Option "Register .NET Environment Variables" angeklickt. Ansonsten werden Sie bei der Arbeit mit .NET Tools am Kommandoprompt einige Probleme haben. Um dies nachträglich zu korrigieren rufen Sie das Setup des .NET Frameworks in der Auflistung der installierten Software (Control Panel, Add or Remove Software) auf und ändern Sie die Einstellung.

Wenn Sie hingegen Visual Studio .NET installiert haben, sind eigentlich keine Änderungen vorzunehmen. Sie verwenden jedoch statt des herkömmlichen Kommandoprompts (cmd.exe) das Visual Studio .NET Command Prompt, welches Sie in der Microsoft Visual Studio .NET Programmgruppe unter Visual Studio .NET Tools finden.

Im Kommandoprompt wechseln wir in das Verzeichnis wo sich die Assembly befindet, und können nun sofort mit Hilfe des Ngen Tools ein Native Image erstellen, indem wir folgendes eingeben:

ngen SimpleExample.dll

Und schon wird ein Native Image erstellt.

Wo ist jetzt das Native Image der Assembly? Sie finden es im GAC (\WinNT\assembly):

Wie Sie sehen, hat unsere Assembly unter der Type-Bezeichnung den Eintrag "Native Images", zuvor war es "Application Extension". Hierzu sind einige Anmerkungen zu machen: Da ich der Einfachheit halber auf eine Assembly-Info Datei verzichtet habe, besteht die Versionsnummer aus einer GUID und die Culture Info ist auf default gesetzt. Weiters ist zu bemerken, daß ich das SN (Strong Name) Utility hier nicht verwendet habe, und somit auch kein Public Key angegeben ist. Im Anwendungsfall sollte dies aber nicht die Regel sein.

Natürlich können Sie auch - falls erforderlich - einige Switches angeben. Allgemein sieht der Syntax für die Verwendung des Tools so aus:

ngen [Optionen] AssemblyPfad AssemblyName

AssemblyPfad ist natürlich der Pfad wo sich die Assembly befindet. Da wir das Tool im gleichen Verzeichnis ausgeführt haben, wo sich unsere Assembly befindet, brauchen wir dies nicht angeben. AssemblyName ist natürlich der eigentliche Name der Assembly. Falls erforderlich, können Sie auch mehr als nur eine Angabe zu einer Assembly machen.

Options ist hier ein Platzhalter für die möglichen Switches. Interessant sind:

Option Bedeutung
/debug Erstellt ein für Debugger verwendbares Image
/delete Löscht bei Angabe der Assembly diese aus dem GAC. Wenn Sie keine Angaben über eine Assembly machen, werden alle von Ngen erzeugten Assemblies gelöscht.
/show Zeigt bei Angabe der Assembly Infos über diese. Wenn Sie keine Angaben über eine Assembly machen, werden alle von Ngen erzeugten Assemblies angezeigt
/prof Erzeugt ein Image, das von einem Profiler verwendet werden kann, der instrumented Code verwendet

Schlußbemerkung

Empfundene Geschwindigkeit ist bei vielen Anwendungen das wichtigste Performancekriterium. Gerade hier zeigen sich bei .NET Schwächen, sobald die Anwendung eine gewisse Größe erreicht - das JITen fordert seine Zeit. Diesen Startnachteil kann man mit NGen mehr als ausgleichen - wird die Anwendung am Zielrechner "pre-JITed", dann passt NGen den Code auf die Zielprozessorarchitektur an. Und das kann sogar zu Geschwindigkeitsvorteilen gegenüber Nicht-.NET Anwendungen führen.

This printed page brought to you by AlphaSierraPapa

Verwandte Artikel

Sprachenintegration in .NET
http:/www.aspheute.com/artikel/20011010.htm

 

©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.