Sizoscope is a binary size investigation tool to help you optimize and reduce the size of your .NET Native AOT binaries.
It supports visualizing the size contributions of individual methods and types, but also namespaces and assemblies. It also allows diffing before/after snapshots and offers basic root cause analysis.
For a cross-platform version of Sizoscope, check SizoscopeX.
$ dotnet tool install sizoscope --global --framework net7.0-windows
The tool only supports the Native AOT deployment model in .NET 7 or later. After enabling Native AOT deployment on your project as documented in the linked doc (basically, add
<PublishAot>true</PublishAot> to a
PropertyGroup in your project), add following lines to the project to enable generation of additional compile-time diagnostic files:
<PropertyGroup> <IlcGenerateMstatFile>true</IlcGenerateMstatFile> <IlcGenerateDgmlFile>true</IlcGenerateDgmlFile> </PropertyGroup>
Once you have that,
dotnet publish your project as usual. After publishing, you should see a *.mstat and *.dgml.xml file under
obj\Release\net[7|8].0\[linux|win]-[x64|arm64]\native - these are the files Sizoscope operates on.
Launch the tool and open the MSTAT file. The associated *.dgml.xml file will be loaded automatically if it's next to the *.mstat. If the *.dgml.xml doesn't exist, root cause analysis will not work.
Once the file loads, you'll be greeted with the main screen that shows assembly contributions:
You can click around things that look interesting. You can also open the search subwindow where you can sort individual entries by exclusive/inclusive size.
If you have a different MSTAT file you'd like to compare with, click the Diff button to enter a diff view:
The diff view will show you things that are unique to the baseline on the left and things that are unique to the compared MSTAT on the right.
ℹ️ NOTE: Root analysis is only supported starting in .NET 8 Preview 4. The MSTAT files generated with older SDKs don't have the necessary information.
The main window and the diff window will show you what is in the binary, but not why it's in the binary. Double-clicking a node in the main window or diff window will open a root analysis window. This will try to explain why something was included.
In the above screenshot, the reason why the top node was included in the executable was all the things nested under it. Some nodes have two reasons. This is typical for e.g. virtual method implementations - the reason why a virtual method implementation is generated is that both the virtual method gets called somewhere and a type implementing the method was allocated. The screenshot has one such situation for