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.