Optimizing footprint of .NET Core applications

A linker is in general a program (tool) used in application compiling process to incorporate together all required program artifacts (DLLs, assemblies, libraries, etc.) needed for an executable program.

The .NET core team is working on a .NET IL Linker version, with the goal to reduce the size of .NET Core applications. If you remember, similar approach was used by .NET native several years ago. Making application footprint small is in many scenarios not really required. But when .NET application has to be download before execution, it is good to have smaller footprint. For example, when application is downloaded from application store. Interestingly Microsoft is working on a project called "Blazor", which will leverage WebAssembly format to execute .NET code in a browser. Because applications, which run in browser, first have to be downloaded, the footprint of application does matter in this scenario too.

To recap, when using .NET IL linker, we want to create application footprint as small as possible.

To demonstrate linker in action, I have used an existing .NET Core 2.0 application. It is in this context an example application, a CLI command line toll inside of daenet IoTService platform.

I used following command line to build and publish my executable:

 publish -c release -r win-x64 -o out

This is nothing new. It creates an application with s called framework independent deployment (FID). As next I added a new nuget configuration to the project:

dotnet new nuget

, and finally pasted following in the newly created nuget configuration:

 <?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="dotnet-core" 
    value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json" />
  </packageSources>
</configuration>

Please not the URI of .NET Core API feed v3 : https://dotnet.myget.org/F/dotnet-core/api/v3/index.json. This feed contains the linker NUGET package ILLink.Task

   <PackageReference Include="ILLink.Tasks" Version="0.1.4-preview-906439" />

As next I build the application with using of IL linker:

publish -c release -r win-x64 -o out /p:LinkDuringPublish=true

Here is the result, which shows differnece in size of two builds:

Build type Size of output Number of items in output folder
Build with IL linker 52,9 MB (55.500.395 bytes) 211
Build without IL Linker 80,4 MB (84.370.552 bytes) 274

If you want to get more details about package compression, execute following statement:

dotnet publish -c release -r win-x64 -o out-with-linker /p:LinkDuringPublish=true /p:ShowLinkerSizeComparison=true

Here is a snapshot of the result :

Assembly Before After Size decrease
iotsvcctl.dll 126.464 126.464 0,00 %
Microsoft.Win32.Registry.dll 85.008 17.920 78,92 %
Microsoft.VisualBasic.dll 465.416 0 100,00 %
. . . . . . . . . . . .
Total 66.180 37.322 43,61 %

Recap

.NET IL Linker is a new tool, which helps making .NET Core application footprint smaller.

In some scenarios, this is not very important, but when application needs to be downloaded from store or from some server, it is important to have small footprint to reduce download time and application startup time. This tool will be used in “Blazor”, which leverage using of WebAssemblies.

References

.NET Core IL Linker on GitHub

Using linker

Blazor