C# erzeugt jetzt auch nativen Code

Microsoft hat mit ".NET Native" einen Compiler für C# vorgestellt, der keine Intermediate Language, sondern direkt Maschinencode erzeugt. Das Unternehmen rückt damit einen Schritt weiter von seiner Zwischensprache und der Just-in-Time-Kompilierung ab.

In Pocket speichern vorlesen Druckansicht 75 Kommentare lesen
Lesezeit: 6 Min.
Von
  • Dr. Holger Schwichtenberg
Inhaltsverzeichnis

Der im Rahmen der BUILD-Konferenz in San Francisco vorgestellte .NET Native liegt erst mal als Vorabversion vor, die als Add-on zu Visual Studio 2013 Update 2 installierbar ist. Zunächst gilt der C#-Compiler nur für Windows Apps, die auf Basis der Windows Runtime (WinRT) in Windows 8.x laufen, nicht aber für klassische Windows-Desktop- und Windows-Server-Anwendungen.

Durch dass Add-on erhalten Windows-App-Projekte einen zusätzlichen Kontextmenüeintrag "Enable .NET Native".

Zusätzlicher Kontextmenüeintrag "Enable .NET Native" ganz unten

Durch diese Aktivierung eröffnen sich in den Projekteigenschaft dann konkrete Einstellungen für die Kompilierung in nativem x64- und ARM-Maschinencode.

Konkrete Einstellungen für die Kompilierung in nativen x64- und ARM-Maschinencode tun sich auf.

Diese Zielprozessorarchitektureinstellungen sind jedoch hier nur zu Testzwecken vorhanden. Eine Windows App sendet der Entwickler wie bisher in Zwischencode in den Windows 8 Store, und die .NET-Native-Kompilierung erfolgt in der Microsoft-Cloud.

Windows und Windows Phone auf Microsofts Build 2014

Microsoft hat auf seiner Entwicklerkonferenz Build 2014 einiges an Neuerungen zu Windows 8.1 und Windows Phone vom Stapel gelassen - immer unter der Prämisse, endlich auch im Tabet- und Smartphone-Bereich besser dazustehen.

Seit der ersten Vorstellung von .NET im Juli 2000 erzeugte der C#-Compiler immer MSIL-Code (Microsoft Intermediate Language), der erst zur Laufzeit von einem Just-in-Time-Compiler (JIT) in Maschinencode für das jeweilige Zielsystem übersetzt wird. Vorteil dieser "Managed Code"-Vorgehensweise ist, dass sich nur ein Binärpaket für beliebige Prozessorarchitekturen verwenden lässt, aber auch, dass Entwickler den Maschinencode für den Befehlssatz des jeweiligen Mikroprozessors optimieren können. Nachteil ist aber ein Leistungsverlust, der sich insbesondere beim Start einer Anwendung oft bemerkbar macht.

Microsoft hatte in den letzten Jahren immer wieder den JIT-Compiler optimiert und das Kaltstartverhalten durch verschiedene Tricks verbessert. Zu den Strategien gehört auch die "Native Code Generation" (NGen), die den Maschinencode in einem zweiten Übersetzungsvorgang schon zur Entwicklungszeit aus der Zwischensprache gewinnt. Das betraf aber immer nur den eigenen Programmcode.

Im neuen .NET-Native-Ansatz liegt aber auch das .NET Framework als optimierter nativer Code (".NET Native Framework") mit minimaler Common Language Runtime (CLR) vor; benötigte Teile des Frameworks werden von einem neuen Compiler mit Namen ilc.exe statisch in die zu erstellende App gelinkt. Im Rahmen des Compilers kommt auch Microsofts C++-Compiler mit den gleichen Optimierungen zum Einsatz, die auch bei C++-Programmcode angewendet werden.

Dieser gravierende Richtungswechsel nach 14 Jahren kommt nicht überraschend; schon 2012 hatte Microsoft im Zuge von Windows 8 mit der Einführung der auf Native Code basierenden neuen Windows-Programmierschnittstelle "Windows Runtime" (WinRT) klargestellt, dass man den Leistungsverlust von Zwischensprachen nicht mehr in Kauf nehmen will.

WinRT ist in C++ geschrieben, aber auch C#-Programmcode kann WinRT über eine sogenannte "Language Projection" nutzen. Dabei lief auch in der Windows-8-Welt der C#-Code bisher über den JIT-Compiler. Bei .NET Native ist dieser Compiler aber nun überflüssig, und es entsteht Maschinencode, der der Ausgabe von Microsofts C++-Compiler ähnelt. Das Entwicklungsteam verspricht vollmundig – im Vergleich zum Einsatz von NGen – um 60[ Prozent verringerte Startzeiten sowie einen um 15 bis 20 Prozent verringerten Speicherbedarf. Und dabei soll auch der Verbreitungsaufwand noch gering und der Produktivitätsvorteil von C# erhalten bleiben.

Der letztere Punkt ist jedoch noch schwer zu glauben, wenn man die dokumentierten Herausforderungen der neuen .NET-Native-Technik sieht. Zum einen werden zahlreiche Funktionen des .NET Frameworks nicht unterstützt, zum Beispiel die SOAP-Webservice-Kommunikation über die Windows Communication Foundation (System.ServiceModel) und die Klassen im Namensraum System.ComponentModel.DataAnnotations. Dabei ist noch zu berücksichtigen, dass sich die Liste nicht auf das vollständige .NET Framework mit über 13.000 Klassen bezieht, sondern nur auf die sowieso schon auf wenige Tausend Klassen abgespeckte Profil ".NET for Windows Store Apps".

Zum anderen gibt es auch funktionelle Unterschiede zwischen .NET Native und dem bisherigen .NET, da einige Teile von .NET auf der Auswertung von Metadaten und Laufzeitkompilierung (z. B. die Serialisierung/Deserialisierung) basieren. Das ist in .NET Native aber nicht vorgesehen, sodass diese Informationen alle zur Entwicklungszeit erstellt werden müssen. Dabei kann laut Microsoft der .NET-Native-Compiler nicht alle Situationen erkennen, in denen er Metadaten vorab kompilieren muss. Daher ist es derzeit Aufgabe des Softwareentwicklers, dem Compiler über eine XML-basierte, sogenannte "Runtime Directives Configuration"-Datei (rd.xml) Hinweise zu geben. Einige aus .NET bekannte Funktionen stehen aber gar nicht zur Verfügung. Dazu gehört insbesondere der Aufruf privatenrKlassenmitglieder via .NET Reflection. In anderen Fällen ist durch eine Umstellung des Programmcodes eine Kompilierung in .NET Native möglich. So kann man zum Beispiel typeof(Name) statt Type.GetType("Name") verwenden.

.NET Native ist eine Weiterentwicklung der bei Windows Phone seit Version 8 eingesetzten Machine Dependent Intermediate Language (MDIL), die in der Microsoft Cloud entsteht. Aktuell ist .NET Native auf C# beschränkt. Unterstützung für Visual Basic soll aber folgen. Native Code entsteht nicht beim Debugging, sodass dies wie bei Managed Code funktioniert. Auch die Speicherverwaltung (Garbage Collection) zur Laufzeit ist wie bei Managed Code.

Dass Microsoft mit Windows Apps den Umstieg auf Native Code begonnen hat, macht Sinn, weil die Arbeiten hier überschaubarer waren als beim vollständigen .NET Framework. Zudem war bei den Apps der Bedarf größer, da die Benutzer schnelle Startzeiten erwarten. Auch wenn Microsoft mit C++ und JavaScript noch zwei andere Sprachen zum Erstellen von Windows Apps anbietet, wurde bisher die deutliche Mehrheit der Windows Apps in Microsofts App-Store mit den .NET-Sprachen C# oder Visual Basic erstellt.

Noch nicht konkret angekündigt, aber durchaus naheliegend ist, dass .NET Native in nicht allzu ferner Zukunft auch für klassische Windows-Anwendungen mit vollständigem .NET Framework verfügbar sein wird. Dann gäbe es für alle .NET-Anwendungen eine durchgehende Native-Code-Strategie zum eigenen Programmcode, über das .NET Framework bis hin zur Betriebssystem-API WinRT. (ane)