4

I am developing a simple, cross-platform .NET application. I need to distribute it as a self-contained deployment as I can't assume if .NET is already installed.

.NET publish for Windows 10 64 bit generates a 64 MB directory. I am pretty sure most of the DLL files are not needed. Is there a way to optimize the distribution so that only the necessary DLL file are kept?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
sumo
  • 61
  • 1
  • 5

4 Answers4

3

I'm facing the same problem. So far, here's what I found:

Microsoft released a Trim tool that finds unused assemblies and removes them.

With .NET CLI:

  • dotnet add package Microsoft.Packaging.Tools.Trimming -v 1.1.0-preview1-25818-01
  • dotnet publish -r win-x64 -c release /p:TrimUnusedDependencies=true

Your application's footprint is now much smaller (normally)


For a better optimization you can use it with ILLinker:

  • dotnet new nuget

Open nuget.config and add <add key="dotnet-core" value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json" />between <packageSource>

Here is an example of what your nuget.config should look like.

Then execute the following commands:

  • dotnet add package ILLink.Tasks -v 0.1.4-preview-981901
  • dotnet add package Microsoft.Packaging.Tools.Trimming -v 1.1.0-preview1-25818-01
  • dotnet publish -r win-x64 -c release /p:TrimUnusedDependencies=true

Using these two tools I managed to divide the size of my application by three.

Source: Reducing the size of self-contained .NET Core applications


I'm still trying to get better optimization. I want to run my ASP.NET Core application (currently 72 MB) in an embedded system with only 10 MB.

If anyone has found a better optimization, I'm a buyer.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
3

Since .NET Core 3.0, it's as simple as adding a flag to your project's .csproj file:

<PropertyGroup>
  <OutputType>Exe</OutputType>
  <TargetFramework>netcoreapp3.0</TargetFramework>
  <RuntimeIdentifier>win-x64</RuntimeIdentifier>
  <PublishSingleFile>true</PublishSingleFile>

  <PublishTrimmed>true</PublishTrimmed> <!-- Add this flag to enable trimming -->
</PropertyGroup>

Then you can just use dotnet publish to generate a trimmed executable.

And here's a warning from the documentation:

It's important to consider that applications or frameworks (including ASP.NET Core and WPF) that use reflection or related dynamic features, will often break when trimmed. This breakage occurs because the linker doesn't know about this dynamic behavior and can't determine which framework types are required for reflection. The IL Linker tool can be configured to be aware of this scenario.

Above all else, be sure to test your app after trimming.

A typical reduction result for a simple console applications seems to be from about 70 MB to about 28 MB.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Paweł Bulwan
  • 8,467
  • 5
  • 39
  • 50
2

Update 2020: This is now part of the toolchain, see Pawel's answer.

This task can be done by using the IL linker. By adding a NuGet package to your project it can reduce the size of the published self-contained application by removing code that is not needed. However, it is still in preview (as of 2017). See the announcement post and sample instructions for self-contained applications.

Martin Ullrich
  • 94,744
  • 25
  • 252
  • 217
  • That's impressive :-) The deployment size got reduced by 50% as the page claims. Very promising but I am not sure I could use this for production use yet. Still boggles my mind I need 32MB for a simple app that interfaces with stdin/stdout, json with newtonsoft and outputs logs with Serilog. Similar app in Python got frozen to 10MB. I am sure this could be apples and oranges comparison. I will follow this linker's progress closely as it could be crucial for micro-services – sumo Dec 29 '17 at 00:43
  • @PeterMortensen you're right. Answers like that are hard as things are changing. – Martin Ullrich Jun 23 '20 at 07:54
0

Microsoft.DotNet.ILCompiler seems to be an even better option than ILLinker. See this reply.

My testing of .NET Core 2.2 self-contained outputs on the same source code gave:

  1. Default self-contained publish: 68 MB
  2. ILLinker: 36 MB
  3. ILCompiler: 5 MB
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Maxim Saplin
  • 4,115
  • 38
  • 29