A few days ago, Microsoft released .NET 7 Preview 7. In this release, they finished most of the work related to Native AOT that was planned for .NET 7. They are planning all the future work for Native AOT here.
I have been following this for a very long time. So why not give it a spin?
Let’s get started.
For .NET 7, Native AOT mainly focuses on console applications. So, let’s create a simple console application:
dotnet new console -n HelloWorld
Program.cs class contains a simple statement to print “Hello, World!”:
Publishing as Single File
Before proceeding to publish using Native AOT, I wanted to know how the same app looks on a single file publish.
So, let’s publish this application as a single file using the .NET CLI command:
dotnet publish -c Release -r win-x64 -p:PublishSingleFile=true --self-contained true
Here if we look at the published output, the size is 64.75 MB. But this includes not just our program but also the runtime because of the use of
--self-contained true flag:
Let’s add one more switch
PublishTrimmed which will remove all the unnecessary code in our application (including all the Base Class Libraries(BCL) and package references):
dotnet publish -c Release -r win-x64 -p:PublishSingleFile=true -p:PublishTrimmed=true --self-contained true
PublishTrimmed option significantly reduces the size to 11.30 MB!
Single file publish includes all the assemblies in a single file. Therefore, it makes the app distribution easier.
But the published output contains Intermediate Language (IL). JIT compiler needs to convert it to native code at runtime. This works great for most scenarios. But it’s not ideal for resource-constrained environments and where the application startup time is crucial.
Let’s add one more switch
PublishReadyToRun. R2R improves the startup performance by compiling the code on the startup path directly to native code. R2R places the native code alongside the IL. Hence, there is a slight increase in the published application size (14.76 MB):
Publishing as Native AOT
Unlike R2R, Native AOT complies entire application to native code just like C++, Go, Rust, and similar others.
Now, let’s go ahead and publish the same console application as Native AOT using the
PublishAot MSBuild property:
dotnet publish -c Release -r win-x64 -p:PublishAot=true
Alternatively, we can specify the property in
.csproj file as well:
<PropertyGroup> <PublishAot>true</PublishAot> </PropertyGroup>
After running the command, with
bin folders removed, it took me under 9 seconds to produce the native binary. But later, it took me under 3 seconds:
Impressive! the application size is only 3.65 MB! The published output is purely native. No Intermediate Language (IL) is present. But why 3.65 MB for a simple “Hello, World!” application you might ask? Well, these results are for good defaults. But, we can further reduce this size. Please look for optimizations here.
We know this is just the beginning and there’s more to come. I just can’t wait to see more real-world projects making use of Native AOT and show us their results. Are you building a cool project using Native AOT? Please let everyone know in the comments!
Also, let’s take a moment to appreciate all the people who were involved in getting this feature out for all of us!
If you wish to read more on publishing using Native AOT, Microsoft has detailed documentation here.
Happy Coding 🙂