CLR

Eine Übersicht der Leistungsverbesserungen in .NET 4.5

Ashwin Kamath

 

Dieser Artikel behandelt die Vorabversion von Microsoft .NET Framework 4.5. Änderungen der entsprechenden Informationen sind vorbehalten.

Den Mitgliedern des Microsoft .NET Framework-Teams war von Anfang an bewusst, das eine Verbesserung der Leistung für Entwickler mindestens ebenso wichtig ist wie das Hinzufügen neuer Laufzeitfeatures und Bibliotheks-APIs. .NET Framework 4.5 umfasst erhebliche Investitionen in die Leistung zum Vorteil aller Anwendungsszenarien. Da .NET 4.5 ein Update von .NET 4 ist, können Ihre .NET 4-Anwendungen darüber hinaus von vielen Leistungsverbesserungen der vorhandenen .NET 4-Features profitieren.

Damit Entwickler zufriedenstellende Anwendungserfahrungen bereitstellen können, sind Startdauer (siehe msdn.microsoft.com/magazine/cc337892), Speicherauslastung (siehe msdn.microsoft.com/magazine/dd882521), Durchsatz und Reaktionsfähigkeit sehr wichtig. Wir legen Zielvorgaben zur Verbesserung dieser Kennzahlen für die unterschiedlichen Anwendungsszenarien fest und entwickeln anschließend Änderungen, um die Vorgaben zu erfüllen oder zu überschreiten. In diesem Artikel wird eine übergeordnete Übersicht über einige der wichtigsten Leistungsverbesserungen gegeben, die wir in .NET Framework 4.5 umgesetzt haben.

CLR

In dieser Version liegt der Schwerpunkt auf: Ausnutzung mehrerer Prozessorkerne zur Verbesserung der Leistung, Reduzierung der Wartezeit im Garbage Collector und Verbesserung der Codequalität systemeigener Images. Nachfolgend sind die wichtigsten Features zur Leistungsverbesserung aufgeführt.

Mehrkern-Just-in-Time (JIT): Wir überwachen kontinuierlich Hardwareentwicklungen auf niedriger Ebene und arbeiten mit Chip-Herstellern zusammen, um die beste hardwaregestützte Leistung zu erzielen. Insbesondere haben wir seit Einführung von Mehrkern-Chips mit diesen in unseren Entwicklungslaboratorien gearbeitet und entsprechende Änderungen vorgenommen, um diese besondere Hardwareentwicklung zu nutzen. Allerdings konnten zunächst nur sehr wenige Kunden von diesen Änderungen profitieren.

Zum jetzigen Zeitpunkt verfügt nahezu jeder PC über mindestens zwei Kerne, sodass neue Features, die mehr als einen Kern erfordern, sofort allgemein genutzt werden können. In eine der ersten Entwicklungsphasen von .NET 4.5 haben wir eruiert, ob es sinnvoll ist, mehrere Prozessorkerne zur gemeinsamen Nutzung der JIT-Kompilierungsaufgabe, insbesondere als Bestandteil des Anwendungsstarts, zu verwenden, um eine insgesamt schnellere Erfahrung zu ermöglichen. Im Rahmen dieser Untersuchung stellten wir fest, dass die Zahl der verwalteten Anwendungen, die einen Mindestschwellenwert von JIT-kompilierten Methoden haben, ausreichend ist, damit sich die Investition lohnt.

Das Feature ist verfügbar, wenn JIT-kompilierte Methoden in einem Hintergrundthread ausgeführt werden, der im Falle eines Mehrkerngeräts auf einem anderen Kern parallel ausgeführt wird. Im Idealfall überholt der zweite Kern die Hauptausführung der Anwendung, sodass die meisten Methoden JIT-kompiliert sind, wenn sie benötigt werden. Um zu ermitteln, welche Methoden kompiliert werden müssen, generiert das Feature Profildaten, die die ausgeführten Methoden verfolgen, und orientiert sich bei einer späteren Ausführung an diesen Profildaten. Die Notwendigkeit, Profildaten zu generieren, stellt die primäre Art und Weise dar, in der Sie mit diesem Feature interagieren.

Mit einer minimalen Codehinzufügung können Sie dieses Feature der Laufzeit dazu nutzen, die Startdauer sowohl der Clientanwendungen als auch der Websites deutlich zu verkürzen. Insbesondere sind direkte Aufrufe von zwei statischen Methoden der ProfileOptimization-Klasse im System.Runtime-Namespace erforderlich. Weitere Informationen finden Sie in der MSDN-Dokumentation. Dieses Feature ist für ASP.NET 4.5-Anwendungen und Silverlight 5-Anwendungen standardmäßig aktiviert.

Optimierte systemeigene Images für mehrere Versionen: Sie haben die Möglichkeit erhalten, den Code für systemeigene Images über ein Tool namens Native Image Generation (NGen) vorzukompilieren. Die folgerichtigen systemeigenen Images führen gegenüber der JIT-Kompilierung in der Regel zu einer deutlich verkürzten Anwendungsstartdauer. In dieser Version haben wir ein Zusatztool namens Managed Profile Guided Optimization (MPGO) eingeführt, mit dem das Layout systemeigener Images zugunsten einer noch besseren Leistung optimiert wird. MPGO setzt eine profilgesteuerte Optimierungstechnologie ein, die dem Konzept des weiter oben beschriebenen Mehrkern-JIT ähnelt. Die Profildaten für die Anwendung umfassen ein repräsentatives Szenario oder eine Gruppe von Szenarien, das bzw. die zur Neuanordnung des Layouts eines systemeigenen Images verwendet werden kann. So lassen sich Methoden und andere Datenstrukturen, die zum Startzeitpunkt erforderlich sind, innerhalb eines Teils des systemeigenen Images dicht nebeneinander anordnen. Dies führt zu einer kürzeren Startzeit und weniger Workingset (Speicherauslastung einer Anwendung). In unseren eigenen Tests und nach unserer Erfahrung bietet MPGO einen Vorteil bei größeren verwalteten Anwendungen (z. B. große interaktive GUI-Anwendungen). Wir empfehlen daher, dieses Tool weitgehend für diese Szenarien einzusetzen.

Das MPGO-Tool generiert Profildaten für eine Intermediate Language (IL)-DLL und fügt das Profil der IL-DLL als Ressource hinzu. Das NGen-Tool dient zur Vorkompilierung von IL-DLLS nach der Profilerstellung und führt auf der Grundlage vorhandener Profildaten zusätzliche Optimierungen aus. Dieser Prozessfluss wird in Abbildung 1 dargestellt.

Process Flow with the MPGO Tool
Abbildung 1: Prozessfluss mit dem MPGO-Tool

Objektheap-Allocator (Large Object Heap, LOH): Viele .NET-Entwickler forderten eine Lösung für das LOH-Fragmentierungsproblem oder eine Möglichkeit, die Komprimierung des LOH zu erzwingen. Weitere Informationen über die Funktionsweise des LOH finden Sie in der Kolumne „Tiefe Einblicke in CLR“ geschrieben von Maoni Stephens vom Juni 2008 unter msdn.microsoft.com/magazine/cc534993. Zusammenfassend gesagt, wird jedes Objekt mit einer Größe von 85.000 Bytes oder mehr dem LOH zugewiesen. Derzeit ist der LOH nicht komprimiert. Die Komprimierung des LOH würde viel Zeit in Anspruch nehmen, da der Garbage Collector große Objekte verschieben müsste, was folglich ein ressourcenintensiver Vorgang wäre. Durch die Erfassung der Objekte im LOH entstehen freie Speicherplätze zwischen den Objekten, die die Erfassung überstehen. Dies führt zu dem bereits erwähnten Fragmentierungsproblem.

Noch einige Worte zur näheren Erläuterung: CLR erstellt eine Freiliste aus inaktiven Objekten, die später zur Erfüllung von Zuordnungsanforderungen für große Objekte wiederverwendet werden können. Angrenzende inaktive Objekte werden in ein einziges freies Objekt umgewandelt. Letztendlich kann für ein Programm die Situation eintreten, dass die Größe dieser freien Speicherfragmente zwischen großen aktiven Objekten für weitere Objektzuweisungen im LOH nicht mehr ausreicht. Da die Komprimierung keine Option darstellt, treten dann schnell Probleme auf. Dies führt dazu, dass Anwendungen nicht mehr reaktionsfähig sind es schließlich zu Ausnahmebedingungen aufgrund unzureichenden Arbeitsspeichers kommt.

In .NET 4.5 wurden einige Änderungen eingeführt, um Speicherfragmente im LOH effizient zu nutzen, insbesondere im Hinblick auf die Verwaltung der Freiliste. Die Änderungen gelten sowohl für die Arbeitsstation als auch die automatische Speicherbereinigung (Garbage Collection, GC) des Servers. Der Grenzwert für 85.000 Byte für LOH-Objekte wird jedoch nicht geändert.              

Hintergrund-GC für Server: In .NET 4 wurde die automatische Hintergrundspeicherbereinigung für die Arbeitsstation-GC ermöglicht. Seitdem hat die Zahl der Geräte mit Heapgrößen im oberen Grenzwertbereich, die zwischen einigen Gigabytes und Gigabytes im zweistelligen Bereich schwanken, zugenommen. Sogar eine optimierte parallel verarbeitete Speicherbereinigung wie die unsere kann mehrere Sekunden für die Bereinigung solcher großen Heaps benötigen und die Anwendungsthreads so sekundenlang blockieren. Mit der automatischen Hintergrundbereinigung für Server werden gleichzeitige Bereinigungen für unsere Serverbereinigung unterstützt. Lange Bereinigungen, die zu Blockierungen führen, werden minimiert, während gleichzeitig ein hoher Anwendungsdurchsatz beibehalten wird.

Wenn Sie die automatische Speicherbereinigung für Server verwenden, müssen Sie keine Schritte ausführen, um dieses neue Feature zu nutzen. Die Server-Hintergrund-GC wird automatisch ausgeführt. Die übergeordneten Merkmale der Hintergrund-GC sind für Client- und Server-GC gleich:

  • Im Hintergrund kann nur die vollständige GC (Generation 2) ausgeführt werden.
  • Die Hintergrund-GC wird nicht komprimiert.
  • Während der Hintergrund-GC kann eine Vordergrund-GC (Generation 0/Generation 1) ausgeführt werden. Die Server-GC wird auf dedizierten Server-GC-Threads ausgeführt.
  • Auf dedizierten Server-GC-Threads wird außerdem die GC mit vollständiger Sperrung ausgeführt.

Asynchrone Programmierung

Im Rahmen von Visual Studio Async CTP wurde ein neues asynchrones Programmiermodell eingeführt, das ein wichtiger Bestandteil von .NET 4.5 geworden ist. Mithilfe dieser neuen Sprachfeatures in .NET 4.5 können Sie asynchronen Code effizient schreiben. Dieses neue Modell wird durch zwei neue Sprachschlüsselwörter in C# und Visual Basic namens „async“ und „await“ ermöglicht. .NET 4.5 wurde außerdem aktualisiert und unterstützt nun asynchrone Anwendungen, die diese neuen Schlüsselwörter unterstützen.

Eine ausgezeichnete Ressource für Beispiele, Whitepapers und Diskussionen über die neuen Sprachfeatures und die Unterstützung stellt das Visual Studio-Portal für asynchrone Programmierung auf MSDN (msdn.microsoft.com/vstudio/async) dar.

Bibliotheken zu parallelem Computing

An den Bibliotheken zu parallelem Computing (PCLs) wurden in .NET 4.5 zahlreiche Verbesserungen vorgenommen, um die vorhandenen APIs zu optimieren.

Schnellere, schlankere Tasks: Die System.Threading.Tasks.Task-Klasse und die Task<TResult>-Klasse wurden optimiert, sodass sie weniger Speicher belegen und in wichtigen Szenarien schneller ausgeführt werden. Insbesondere Szenarien in Bezug auf das Erstellen von Tasks und Planen von Fortsetzungen erfuhren eine Leistungsverbesserung von bis zu 60 Prozent.

Mehr parallel ausgeführte PLINQ-Abfragen: PLINQ weicht auf die sequenzielle Ausführung aus, wenn die parallele Verarbeitung einer Abfrage negative Folgen hätte (Verlangsamung des Systems). Diese Entscheidungen sind fundierte Annahmen und treffen nicht immer perfekt zu. In .NET 4.5 erkennt PLINQ mehr Abfragenklassen, als parallel erfolgreich verarbeitet werden können.

Schnellere simultane Auflistungen: An der System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>-Klasse wurden zahlreiche Anpassungen vorgenommen, um sie für bestimmte Szenarien zu beschleunigen.

Weitere Informationen zu diesen Anpassungen finden Sie im Parallel Computing Platform-Teamblog unter blogs.msdn.com/b/pfxteam.

ADO.NET

Unterstützung für Null-Bit-Komprimierung auf Zeilenebene: Nulldaten kommen besonders bei Kunden vor, die das SQL Server 2008-Feature für Spalten mit geringer Dichte verwenden. Kunden, die dieses Feature verwenden, können potenziell Ergebnissätze erzeugen, die eine große Zahl von Nullspalten enthalten. Für dieses Szenario wurde die Null-Bit-Komprimierung auf Zeilenebene (SQLNBCROW-Token oder einfach NBCROW) eingeführt. Dadurch wird der Platz, der von den Ergebnissatzzeilen belegt wird, die vom Server mit vielen Spalten gesendet werden, durch Komprimierung mehrerer Spalten mit NULL-Werten in eine Bitmaske reduziert. Dies ist für die Datenkomprimierung des TDS-Protokolls (Tabular Data Stream, tabellenförmiger Datenstrom) sehr hilfreich, dessen Daten zahlreiche Nullspalten enthalten.

Entity Framework

Automatisch kompilierte LINQ-Abfragen: Wenn Sie heute eine LINQ to Entities-Abfrage schreiben, läuft das Entity Framework über die Ausdrucksstruktur, die vom C#/Visual Basic Compiler generiert wurde, und übersetzt (oder kompiliert) diese in SQL, wie in Abbildung 2 gezeigt.

A LINQ to Entities Query Translated into SQL
Abbildung 2: Eine in SQL übersetzte LINQ to Entities-Abfrage

Die Kompilierung der Ausdrucksstruktur in SQL umfasst jedoch einigen Aufwand, insbesondere bei komplexeren Abfragen. In vorherigen Versionen des Entity Framework musste die CompiledQuery-Klasse verwendet werden, wenn Sie diese Leistungseinbußen bei der Ausführung einer LINQ-Abfrage nicht hinnehmen wollten.

Diese neue Entity Framework-Versionen unterstützt ein neues Feature für automatisch kompilierte LINQ-Abfragen. Jetzt wird jede ausgeführte LINQ to Entities-Abfrage automatisch kompiliert und in den Entity Framework-Cache für Abfragepläne zwischengespeichert. Wenn Sie die Abfrage noch einmal ausführen, greift das Entity Framework in seinem Cache für Abfragen darauf zu und muss nicht den gesamten Kompilierungsprozess erneut ausführen. Weitere Informationen über diese Funktion finden Sie unter bit.ly/iCaM2b.

Windows Communication Foundation und Windows Workflow Foundation

Das Windows Communication Foundation (WCF)- und das Windows Workflow Foundation (WF)-Team hat außerdem zahlreiche Leistungsverbesserungen in dieser Version vorgenommen, wie:

  • Verbesserungen bei der Skalierbarkeit der TCP-Aktivierung: Von den Kunden wurde ein Problem mit der TCP-Aktivierung gemeldet. Wenn viele Benutzer simultan Anforderungen mit konstanten Verbindungen senden, zeigte der TCP-Portfreigabedienst keine gute Skalierungsleistung. Dieses Problem wurde in .NET 4.5 behoben.
  • Integrierte Unterstützung für die GZip-Komprimierung für WCF HTTP/TCP: Mit dieser neuen Komprimierung erwarten wir ein um das Fünffache besseres Komprimierungsverhältnis.
  • Wiederverwendung des Hosts bei hoher Speicherauslastung für WCF: Wenn die Speicherauslastung hoch ist (konfigurierbarer Knopf), setzen wir LRU-Logik (Least Recently Logic) ein, um die WCF-Dienste wiederzuverwenden.
  • Asynchrone HTTP-Streamingunterstützung für WCF: Dieses Feature wurde in .NET 4.5 implementiert und erzielte denselben Durchsatz wie das synchrone Streaming, jedoch mit deutlich besserer Skalierbarkeit.
  • Fragmentierungsverbesserungen der Generation 0 für WCF TCP.
  • Optimierter BufferManager für WCF für große Objekte: Für große Objekte wurde ein besseres Puffer-Pooling implementiert, um hohe GC-Kosten für Generation 2 zu vermeiden.
  • Verbesserung der WF-Validierung durch Zwischenspeichern von Ausdrücken: Wir erwarten bis zu drei Verbesserungen für ein Hauptszenario, in dem WF geladen und ausgeführt wird.
  • Implementierung von WCF/WF Ende-zu-Ende-Ereignisablaufverfolgung für Windows (ETW): Hierbei handelt es sich zwar nicht um ein Feature zur Verbesserung der Leistung, doch unterstützt es die Kunden bei Leistungsanalysen.

Weitere Details finden Sie im Workflow-Teamblog unter blogs.msdn.com/b/workflowteam und im MSDN Library-Artikel unter bit.ly/n5VCtU.

ASP.NET

Zwei wichtige Leistungsziele für das ASP.NET-Team für .NET 4.5 waren die Verbesserung der Websitedichte (auch als „Speicherverbrauch pro Website“ definiert) und die Kaltstartzeit von Websites in einer gemeinsamen Hostingumgebung.

In Szenarien mit gemeinsamem Hosting wird der gleiche Computer von vielen Websites verwendet. In diesen Umgebungen ist der Datenverkehr in der Regel niedrig. Von einigen Hostingunternehmen bereitgestellte Daten zeigen, dass der Wert Anforderung pro Sekunde (rps) unter 1 rps mit gelegentlichen Spitzen von 2 rps oder mehr liegt. Dies bedeutet, dass viele Arbeitsprozesse wahrscheinlich abgebrochen werden, wenn sie sich für einen längeren Zeitraum (standardmäßig 20 Minuten in IIS 7 und höher) im Leerlauf befinden. Diese Startzeit wird zu einem sehr wichtigen Faktor. In ASP.NET ist dies die Zeit, die verstreicht, bis eine Website eine Anforderung erhält und darauf antwortet. Hierbei wird der Fall, wenn der Arbeitsprozess inaktiv war, mit dem Fall, wenn die Website bereits kompiliert war, verglichen.

In dieser Version haben wir mehrere Features implementiert, um die Startzeit für die Szenarien mit gemeinsamem Hosting zu verbessern. Folgende Features wurden implementiert:

  • Internalisierung von Bin-Assemblys (Freigabe gemeinsamer Assemblys): Mit dem Schattenkopiefeature in ASP.NET können in einer Anwendungsdomäne verwendete Assemblys aktualisiert werden, ohne dass die entsprechende AppDomain entladen werden muss (erforderlich, da die CLR verwendete Assemblys sperrt). Hierzu werden Anwendungsassemblys an einen separaten Speicherort kopiert (der entweder standardmäßig von der CLR bestimmt oder vom Benutzer festgelegt wird). Die Assemblys werden dann von diesem Speicherort geladen. So kann die ursprüngliche Assembly aktualisiert werden, während die Schattenkopie gesperrt wird. ASP.NET aktiviert dieses Feature standardmäßig für Assemblys des Bin-Ordners, sodass DLLs aktualisiert werden können, während eine Website aktiv ist und ausgeführt wird.
  • ASP.NET erkennt den Bin-Ordner einer Website als speziellen Ordner für kompilierte Assemblys (DLLs) für benutzerdefinierte ASP.NET-Steuerelemente, Komponenten oder anderen Code, der in einer ASP.NET-Anwendung referenziert und auf verschiedenen Seiten der Website gemeinsam verwendet werden muss. Eine kompilierte Assembly im Bin-Ordner wird automatisch überall in der Webanwendung referenziert. ASP.NET erkennt außerdem die aktuelle Version einer spezifischen DLL im Bin-Ordner, die von der Website verwendet werden soll. Vordefinierte Anwendungen, die für die Verwendung durch ASP.NET-Websites bestimmt sind, werden in der Regel im Bin-Ordner und nicht im globalen Assemblycache installiert.
  • Die ASP.NET- und CLR-Teams haben festgestellt, dass eine große Anzahl der Schattenkopie-DLLs identisch ist, wenn sich viele Websites auf demselben Server befinden und dieselbe Anwendung nutzen. Da diese Dateien vom Datenträger gelesen und in den Speicher geladen werden, führt dies zu zahlreichen redundanten Ladevorgängen, die die Startzeit und den Speicherverbrauch erhöhen. Wir haben an symbolischen Links für die CLR gearbeitet und die Identifizierung gemeinsamer Dateien implementiert und sie an einem bestimmten Speicherort internalisiert (auf den die symbolischen Links zeigen). ASP.NET konfiguriert das Erstellen von Schattenkopien für DLLs, die sich im Bin-Ordner befinden, automatisch. Gemeinsam genutzte Hoster können ihre Computer nun den ASP.NET-Richtlinien entsprechend einrichten, um eine maximale Leistung zu erzielen.
  • Mehrkern-JIT: Die entsprechenden Informationen können Sie dem vorherigen Abschnitt „CLR“ entnehmen. Das ASP.NET-Team verwendet das Mehrkern-JIT-Feature zur Verbesserung der Startzeit, indem die JIT-Kompilierung über mehrere Prozessorkerne verteilt wird. Dieses Feature ist in ASP.NET standardmäßig aktiviert, sodass Sie es ohne zusätzlichen Aufwand nutzen können. Zum Deaktivieren der Funktion ändern Sie die folgende Einstellung in Ihrer WEB.CONFIG-Datei:
<configuration>
<!-- ... -->
<system.web>
<compilation profileGuidedOptimizations="None" />
<!-- ... -->
  • Vorabruf: Durch die Vorabruftechnologie in Windows kann der Aufwand für das Lesen vom Datenträger für Paging während des Anwendungsstarts effektiv reduziert werden. Die Vorabruffunktion ist jetzt auch auf Windows Server aktiviert (allerdings nicht standardmäßig). Zur Aktivierung des Vorabrufs für Webhosting mit hoher Dichte führen Sie die folgenden Befehle in der Befehlszeile aus:
sc config sysmain start=auto
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParameters" /v EnablePrefetcher /t REG_DWORD /d 2 /f
reg add "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Prefetcher" /v MaxPrefetchFiles /t REG_DWORD /d 8192 /f
net start sysmain
  • Anschließend können Sie die Datei WEB.CONFIG zur Verwendung in ASP.NET aktualisieren:
<configuration>
<!-- ... -->
<system.web>
<compilation enablePrefetchOptimization
  ="true" />
<!-- ... -->
  • GC-Anpassung für Webhosting mit hoher Dichte: GC kann sich auf den Speicherverbrauch einer Website auswirken, lässt sich jedoch anpassen, um die Leistung zu verbessern. Sie können GC zugunsten einer besseren CPU-Leistung (Häufigkeit der Auflistungen reduzieren) oder zugunsten eines niedrigeren Speicherverbrauchs anpassen oder konfigurieren (d. h. häufigere Auflistungen, um Speicherplatz früher freizumachen). Zur Aktivierung der GC-Anpassung wählen Sie die HighDensityWebHosting-Einstellung in der ASPNET.CONFIG-Datei im Windows\Microsoft\v4.0.30319-Ordner aus, um einen geringeren Speicherverbrauch (Workingset) pro Website zu erzielen:
<configuration>
<!-- ... -->
<runtime>
<performanceScenario
  value="HighDensityWebHosting" />
  <!-- ... -->

Weitere Informationen zu den ASP.NET-Leistungsverbesserungen finden Sie im Whitepaper „Erste Schritte mit der nächsten Version von ASP.NET“ unter bit.ly/A66I7R.

Feedback

Die hier angegebene Liste ist nicht vollständig. Es sind zahlreiche kleinere Änderungen zur Verbesserung der Leistung implementiert, die ausgelassen wurden, um diesen Artikel auf die wichtigsten Features zu beschränken. Darüber hinaus haben die .NET Framework-Leistungsteams an Leistungsverbesserungen insbesondere für von Windows 8 verwaltete Anwendungen im Metrostil gearbeitet. Nachdem Sie .NET Framework 4.5 und Visual Studio 11 Beta für Windows 8 heruntergeladen und ausprobiert haben, teilen Sie uns bitte Ihr Feedback oder Vorschläge für künftige Versionen mit.

Glossar

Gemeinsames Hosting: Webhosting mit hoher Dichte, auch als „gemeinsames Webhosting“ bezeichnet, ermöglicht die Ausführung von Hunderten, wenn nicht Tausenden von Websites auf demselben Server. Durch Teilen der Hardwarekosten kann jede Website kostengünstiger gewartet werden. Diese Technik hat die Einstiegsschwelle für Websitebesitzer deutlich gesenkt.

Kaltstart: Mit Kaltstart wird die Zeit bezeichnet, die zum Starten Ihrer Anwendung erforderlich ist, wenn diese noch nicht im Speicher vorhanden war. Zu einem Kaltstart kann es kommen, wenn Sie eine Anwendung nach einem Systemneustart starten. Für große Anwendungen kann der Kaltstarte mehrere Sekunden in Anspruch nehmen, da die erforderlichen Seiten (Code, statische Daten, Registrierung usw.) nicht im Speicher vorhanden sind und kostspielige Datenträgerzugriffe erforderlich sind, um die Seiten in den Speicher zu laden.

Warmstart: Mit Warmstart wird die Zeit bezeichnet, die zum Starten einer Anwendung erforderlich ist, die bereits im Speicher vorhanden ist. Wenn eine Anwendung z. B. einige Sekunden zuvor gestartet wurde, sind die meisten Seiten wahrscheinlich bereits in den Speicher geladen und werden vom Betriebssystem wiederverwendet. Damit wird kostspielige Datenträgerzugriffszeit eingespart. Dies ist der Grund dafür, warum eine Anwendung deutlich schneller gestartet wird, wenn Sie sie zum zweiten Mal ausführen (aus dem gleichen Grund wird eine zweite .NET-Anwendung schneller gestartet als die erste, da Teile der .NET-Anwendung bereits in den Speicher geladen wurden).

Native Image Generation oder NGen (Erstellen systemeigner Images): NGen bezieht sich auf den Prozess der Vorkompilierung von IL-Anwendungen (Intermediate Language) in Computercode vor der Ausführungszeit. Dies führt zu zwei wesentlichen Leistungsvorteilen. Erstens wird die Dauer zum Starten der Anwendung verringert, da eine Kompilierung zur Ausführungszeit vermieden wird. Zweitens wird die Speichernutzung verbessert, da ein gemeinsames Verwenden der Codepages durch mehrere Prozesse unterstützt wird. Mit dem NGen.exe-Tool werden systemeigene Images erstellt und im systemeigenen Imagecache (NIC) des lokalen Computers installiert. Zur Laufzeit werden systemeigene Images geladen, wenn sie verfügbar sind.

Profilgesteuerte Optimierung: Mit der profilgesteuerten Optimierung lassen sich nachweislich die Start- und Ausführungszeiten von systemeigenen und verwalteten Anwendungen verbessern. Windows stellt das Toolset und die Infrastruktur bereit, um die profilgesteuerte Optimierung für systemeigene Assemblys durchzuführen. Dahingegen stellt die CLR das Toolset und die Infrastruktur für profilgesteuerte Optimierungen verwalteter Assemblys (die sogenannte Managed Profile Guided Optimization oder MPGO) bereit. Diese Technologien werden von vielen Teams bei Microsoft zur Verbesserung der Leistung ihrer Anwendungen eingesetzt. Die CLR führt z. B. eine profilgesteuerte Optimierung von systemeigenen Assemblys (profilgesteuerte C++-Optimierung) und von verwalteten Assemblys (mit MPGO) durch.

Garbage Collector: Die .NET-Laufzeit unterstützt die automatische Speicherverwaltung. Sie verfolgt jede vom verwalteten Programm vorgenommene Speicherzuweisung und ruft regelmäßig einen Garbage Collector auf, der nicht mehr verwendeten Speicher findet und diesen für neue Zuweisungen nutzt. Eine wichtige vom Garbage Collector durchgeführte Optimierung besteht darin, dass nicht der gesamte Heap jedes Mal durchsucht wird, sondern der Heap in drei Generationen partitioniert wird (Generation 0, Generation 1 und Generation 2). Weitere Informationen zum Garbage Collector finden Sie in der Kolumne „Tiefe Einblicke in CLR“ vom Juni 2009 unter msdn.microsoft.com/magazine/dd882521.

Komprimierung: Im Zusammenhang mit Garbage Collection bedeutet dies, dass der Garbage Collector den Heap komprimiert, wenn dieser einen ausreichend fragmentierten Zustand erreicht hat, indem aktive Objekte nah zueinander verschoben werden. Das primäre Ziel der Komprimierung des Heaps besteht darin, größere Speicherblöcke verfügbar zu machen, denen mehr Objekte zugewiesen werden können.

Ashwin Kamath arbeitet als Program Manager im CLR-Team von .NET und war maßgeblich an der Entwicklung der Leistungs- und Zuverlässigkeitsfeatures für .NET Framework 4.5 beteiligt. Derzeit arbeitet er an der Entwicklung von Diagnosefeatures für die Windows Phone-Entwicklungsplattform.

Unser Dank gilt den folgenden technischen Experten für die Durchsicht dieses Artikels: Surupa Biswas, Eric Dettinger, Wenlong Dong, Layla Driscoll, Dave Hiniker, Piyush Joshi, Ashok Kamath, Richard Lander, Vance Morrison, Subramanian Ramaswamy, Jose Reyes, Danny Shih und Bill Wert