What I’ve learned about .NET Native

As I wrote yesterday, I finally have the entire .NET Core runtime and tools installed on my Linux work laptop, including:

(I’m going to refer to ASP.NET 5 as ASP.NET Core from now on, as per the naming announcement.)

Last night I started testing various ASP.NET Core projects ā€” which have, up to now, been running on the Mono runtime ā€” on CoreCLR/CoreFx instead. So far they’ve all worked, although admittedly I am leaving the ones I am expecting problems with until last, especially those that use the more edge-casey parts of the Azure Storage SDK. šŸ™‚

When I’ve got access to my big ol’ desktop box, I’m going to run some load tests against the various services running in both CoreCLR and Mono Docker containers, and I’ll publish the results of that experiment here.

But over the course of the last couple of days I’ve dug around in the various repositories of the dotnet organisation on GitHub, and what I’m seeing there is very exciting. And I’m not just talking about running on Linux.

The new CLI

The new dotnet CLI is very different from the dnx, dnu and dnvm commands I’ve been using for the last year or so. Those are shell scripts (or Bash functions); if you cat `which dnx` you can see the script, which runs a .NET DLL using Mono.

If you cat `which dotnet` you’ll get a screen full of gibberish, because dotnet is a native executable.

I don’t know exactly what’s going on in there at present. Poking around in that dotnet-nightly folder shows a lot of native executables that all seem to be the same size, which is odd, and maybe they’re just loaders for the .NET assemblies around them, but this is still pretty cool.


Curiosity about what made this possible led me to the CoreRT repository, which describes CoreRT as

a .NET Core runtime optimized for AOT (ahead of time compilation) scenarios, with the accompanying .NET Native compiler toolchain.

The what-now toolchain?

Hiding in the Documentation folder I found the file, which explains what’s going on.

The developers of this project (which I think includes contributors both inside and outside Microsoft) are building a set of tools that will take MSIL byte-code (produced by compiling C# code using Roslyn), and ahead-of-time compile that to native x86/64 machine code.

The initial default implementation uses RyuJIT, the new 64-bit CLR JIT compiler (released last summer), to produce the machine code, but the toolchain can also use other compilers, including their own reference IL-to-C++ compiler (which is amazingly short) and LLILC, which is currently a JIT compiler for CoreCLR that uses LLVM, but which is intended to support AOT compilation in the future.

A quick note about JIT vs AOT

The .NET CLR includes a Just-In-Time (JIT) compiler, which is responsible for converting the MSIL bytecode into native machine code. It does this while your application is running, and it compiles each method the first time it is called; hence, “just in time”. This is how the same assembly can be used on different CPUs and operating systems.

JIT compilers, as a rule, are optimised to do their job as quickly as possible, rather than to produce the best machine code possible.

An Ahead-Of-Time (AOT) compiler converts all the MSIL bytecode to native machine code up-front, for a specific target CPU and operating system, so you can distribute the application or library without the need for a separate runtime.

Because AOT compilers don’t have the same micro-time constraints as JIT compilers, in many cases they can produce more efficient, highly-optimised machine code.

CoreRT itself appears to be a modified version of the CoreCLR and libraries, with things organised in different ways and dependencies cleaned up. I’m speculating that this is ā€” at least in part ā€” to enable more efficient dead code elimination so that the native binaries are as small as possible.

This all means that C# is about to enter Go territory ā€“ a cross-platform, natively-compiled, garbage-collected programming language. Except, of course, that C# has modern language features like generics, async/await, etc.

Native ASP.NET Core

On that same page, under Roadmap, it says:

To start, we are targeting native executables (AKA "console apps"). Over time, we’ll extend that to include ASP.NET 5 apps…

So beyond even the current "XCOPY deployment" model for ASP.NET Core web applications, where you simply dump a directory tree onto a server, we can expect a "COPY deployment" model, where you just dump a single executable file. As the same page says, this could lead to Dockerfiles that look like this:

FROM debian:jessie


ADD mycompiledapp.exe /
# The .exe is just there to make a point :)

ENTRYPOINT /mycompiledapp

It’s not clear whether this toolchain will be able to statically-link non-.NET libraries (e.g. libuv or libcurl) into the native binaries, or whether they’ll need to be installed alongside as dynamically-linked .dll or .so files. Either way, this is going to make for very small Docker images, and containers that start up very quickly, but that train of thought quickly leads to wondering about unikernels… Will .NET Native be able to support those?

The preliminary answer, at least, would seem to be "Yes. Yes it will."

Obviously these projects are in the early stages, and it never does to get too excited too far in advance lest things are brutally murdered further down the roadmap, but all in all, I’d say it’s a good time to be a C# developer.

Hat tip: I was inspired to jump down this particular rabbit hole by Tugberk Ugurlu’s recent blog post about this stuff.

Share on facebook
Share on google
Share on twitter
Share on linkedin


Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.