Programming languages seem to be cyclical. Low level languages give developers the chance to have very fast code with the minimum of commands necessary, but the closer you code to hardware the more difficult it becomes, and the developer should have a good grasp of the hardware in order to get the best performance. In theory, everything could be written in assembly language but that has some limitations. Programming languages, over time, have been abstracted from the hardware they run on which gives advantages to developers in that they do not have to micro-manage their code, and the code itself can be compiled against different architectures.

In the end, the processor just executes machine code, and job of moving from a developer’s mind to machine code can be done in a several ways. Two of the most common are Ahead-of-Time (AOT) and Just-in-Time (JIT) compilation. Each have their own advantages, but AOT can yield better performance because the CPU is not translating code on the fly. For desktops, this has not necessarily been a big issue since they generally have sufficient processing power anyway, but in the mobile space processors are much more limited in resources, especially power.

We’ve seen Android moving to AOT with ART just last year, and the actual compilation of the code is done on the device after the app is downloaded from the store. With Windows, apps can be written in more than just one language, and apps in the Windows Store can be written in C++, which is compiled AOT, as well as C# which runs as JIT code using Microsoft’s .NET framework, or even HTML5, CSS, and Javascript.

With .NET Native, Microsoft is now allowing C# code to be pre-compiled to native code, eliminating the need to fire up the majority of the .NET framework and runtime, which saves time at app launch. Visual Studio will now be able to do the compile to native code, but Microsoft is implementing quite a different system than Google has done with Android’s ART. Rather than having the developer do the compilation and upload to the cloud, and rather than have the code be compiled on the device, Microsoft will be doing the compilation themselves once the app is uploaded to the store. This will allow them to use their very well-known C++ compiler, and any tweaks they make to the compiler going forward will be able to be applied to all .NET Native apps in the store rather than having to get the developer to recompile. Microsoft's method is actually very similar to Apple's latest changes as well, since they will also be recompiling on their end if they make changes to their compiler.

They have added some pretty interesting functionality to their toolkit to enable .NET Native. Let’s take a look at the overview.

Starting with C# code, this is compiled into IL code using the same compiler that they use for any C# code running on the .NET framework as JIT code. The resulting Intermediate Language code is actually the exact same result as someone would get if they wanted to run the code as JIT. If you were not going to compile to native, you would stop right here.

To move this IL code to native code, next the code is run through an Intermediate Language Complier. Unlike a JIT compiler which runs on the fly when the code is running, the ILC can see the entire program and can therefore make larger optimizations than the JIT compiler would be able to do since it only sees a tiny portion of the code. ILC also has access to the .NET framework to add in the necessary code for standard functions. The ILC will actually create C# code for any WinRT calls made to avoid the framework having to be invoked during execution. That C# code is then fed back into the toolchain as part of the overall project so that all of these calls can be static calls for native code. The ILC then does transforms on any C# code that are required; C# code can rely on the framework for certain functions, so these need to be transformed since the framework will not be invoked once the app is compiled as native. The resulting output from the ILC is one file which contains all of the code, all of the optimizations, and any of the .NET framework necessary to run this app. Next, the single monolithic output is put through a Tree Shaker which looks at the entire program and determines what code is being used, and what is not, and expunging code that is never going to be called.

The resultant output from ILC.exe is Machine Dependent Intermediate Language (MDIL) which is very close to native code but with a light abstraction of the native code. MDIL contains placeholders which must be replaced before the code can be run by a process called binding.

The binder, called rhbind.exe, changes the MDIL into a final set of outputs which results in a .exe file and a .dll file. This final output is run as native code, but it still relies on a minimal runtime to be active which contains the garbage collector.

The process might seem pretty complicated, with a lot of steps, but there is a method to the madness. By keeping the developer’s code as an IL and treating it just like it would be non-native code, the debugging process is much faster since the IDE can run the code in a virtual machine with JIT and avoid having to recompile all of the code to do any debugging.

The final compile will be done in the cloud for any apps going to the store, but the tools will be available locally as well to assist with testing the app before it gets deployed to ensure there are no unseen consequences of moving to native code.

All of this work is done for really one reason. Performance. Microsoft’s numbers for .NET Native shows up to 60% quicker cold startup times for apps, and 40% quicker launch with a warm startup. Memory usage will also be lower since the operating system will not need to keep the runtime active at the same time. All of this is important for any system, but especially for low powered tablets and phones.

Microsoft has been testing .NET Native with two of their own apps. Both Wordament and Fresh Paint have been running as native code on Windows 8.1. This is the case for both the ARM and x86 versions of the app, and the compilation in the cloud ensures that the device downloading will be sure to get the correct executable for its platform.

Microsoft Fresh Paint

.NET Native has been officially released with Visual Studio 2015, and is available for use with the Universal Windows App platform and therefore apps in the store. At this time, it is not available for desktop apps, although that is certainly something that could come with a future update. It’s not surprising though, since they really want to move to the new app platform anyway.

There is a lot more under the covers to move from managed code to native code, but this is a high level overview of the work that has been done to provide developers with a method to get better performance without having to move away from C#.

Source: MSDN

Comments Locked

30 Comments

View All Comments

  • JohnGalt1717 - Friday, October 2, 2015 - link

    No it isn't. All of the Java apps could benefit from exactly the same process because Java works almost identically to .NET in that it's compiled to IL which is executed by the JIT. By fully compiling these there would be MASSIVE improvements in speed and size of apps. (and Xamarin etc. wouldn't take a penalty any longer either.)
  • FieryUP - Friday, October 2, 2015 - link

    I agree, although there are a lot more targets than that. ARMv7, ARMv7e, 32-bit ARMv8, 64-bit ARMv8, x86 (32-bit), x64, MIPS, MIPS64 at a bare minimum.
  • Morawka - Friday, October 2, 2015 - link

    i dont think you target 32bit armv8 but i might be wrong, i thought the ARMv8 64 had all the backwards compatibility.
  • da_asmodai - Wednesday, October 7, 2015 - link

    Because Microsoft's method means the platform is limited to only the hardware the Microsoft Store supports generating native code for. Google's method of having the user compile at install means the platform can support any hardware, google only stores the platform independ code. If an OEM makes a new hardware platform, for example Samsung makes a new Exynos chip, then Samsung grabs the AOSP code and modifies it to meet their custom hardware needs. Then users just download the hardware independent IL Code (byte code in java terms) from the google core and the hardware specific compiler on their specific device compiles the byte code to native code at install time. In both cases when the user goes to run the app they're running native code but the MS way is limited to whatever MS decides to support and puts the responsibility on Microsoft to support new hardware. On the other hand the Google way is not limited by Google and the responsibility to tune the compiler to the hardware falls on the hardware maker who knows the hardware the best (using the Google provided AOSP code as a framework).
  • JohnGalt1717 - Friday, October 2, 2015 - link

    FYI MS also just announced shared .NET fully compiled libraries that will automatically be downloaded as needed. This further shrinks the compiles because they're no longer linking the .NET components into the .exe/.dll and instead they're shared with other apps (which also can save memory because the .net components can be shared although still fully compiled)

    Download usage savings is pretty huge.
  • ruthan - Friday, October 2, 2015 - link

    Hmm, fast start up is good, but biggest C# problem besides portability is performance. Will this help to app performance and how much?

    Because for example Unity3D games engine using C# Mono.Net port and performance is biggest issue of whole engine.
  • Agent_007 - Friday, October 2, 2015 - link

    I would say the biggest problem of Unity performance is OLD Mono version that they use (if they used e.g. Mono 4.0, performance would be much better, specially garbage collection performance).

    But Unity is moving to IL2CPP (iOS and WebGL are already using it) so Mono performance won't matter in future.
    http://blogs.unity3d.com/2015/01/29/unity-4-6-2-io...
  • CSMR - Friday, October 2, 2015 - link

    The flowchart suggests Microsoft is doing it properly with an IL to native compiler. But why then is it C# only rather than supporting any .net language -> IL -> native?
  • Gigaplex - Friday, October 2, 2015 - link

    According to Microsoft's developer site, both C# and VB.NET work with .NET Native. Those are the only 2 .NET languages supported in WinRT I believe.
  • prisonerX - Sunday, October 4, 2015 - link

    Natively compiled languages have been faster than hand written assembler for some time now. There are very few reasons to use it these days.

Log in

Don't have an account? Sign up now