NativeAOT CLI size and startup analysis for dotnet/sdk#55497
PR: dotnet/sdk#55497 — Enable MSBuild-backed commands in the Native AOT CLI
- OS/RID: Windows x64 (
win-x64) - Configuration:
Release - PR base:
2e5fa46b2d150671d77cf313930d4de322907118 - PR head:
3df559618a8d1776b58dd71c3b4c2ab424b46ab8 - SDK used to build:
11.0.100-preview.5.26302.115 - NativeAOT compiler/runtime packs:
11.0.0-preview.7.26365.101 - Each bundle was force-recompiled to prevent incremental output reuse.
- Bundle size is the native
dotnet-aot.dllonly. PDB size is excluded. - Commands were launched through the NativeAOT
dnhost withDOTNET_CLI_ENABLEAOT=true.
| Optimization | Invariant globalization | Base | PR | PR increase |
|---|---|---|---|---|
| Speed | false | 20.60 MiB | 45.79 MiB | +25.18 MiB / 122.2% |
| Size | false | 17.16 MiB | 36.28 MiB | +19.12 MiB / 111.4% |
| Speed | true | 20.39 MiB | 45.54 MiB | +25.15 MiB / 123.3% |
| Size | true | 16.97 MiB | 36.06 MiB | +19.09 MiB / 112.5% |
On the PR head:
OptimizationPreference=Sizesaves 9.51 MiB / 20.8% with normal globalization.OptimizationPreference=Sizeplus invariant globalization saves 9.73 MiB / 21.3% versus the default.InvariantGlobalization=truealone saves only 0.22–0.25 MiB / ~0.6% on Windows.
| PE section | Base | PR | Increase | Share of growth |
|---|---|---|---|---|
.text |
8.43 MiB | 18.03 MiB | +9.60 MiB | 38.1% |
.rdata |
10.35 MiB | 23.45 MiB | +13.09 MiB | 52.0% |
.data |
0.82 MiB | 1.72 MiB | +0.90 MiB | 3.6% |
.pdata |
0.48 MiB | 1.08 MiB | +0.60 MiB | 2.4% |
.reloc |
0.52 MiB | 1.50 MiB | +0.99 MiB | 3.9% |
Most of the increase is code and read-only data, consistent with resolver registration rooting the MSBuild/NuGet dependency closure.
These are medians from 150 launches per command/configuration. Commands were rotated across three passes to reduce ordering effects. Output was identical across all four configurations.
| Command | Speed | Size | Speed + invariant | Size + invariant |
|---|---|---|---|---|
--version |
27.40 ms | 40.47 ms | 26.28 ms | 39.58 ms |
--info |
55.47 ms | 68.87 ms | 45.45 ms | 58.61 ms |
--help |
27.79 ms | 40.84 ms | 26.93 ms | 39.93 ms |
build --help |
27.97 ms | 41.36 ms | 27.75 ms | 40.12 ms |
restore --help |
28.74 ms | 41.89 ms | 27.41 ms | 40.88 ms |
sdk check |
108.06 ms | 117.27 ms | 90.30 ms | 106.41 ms |
| Command | Size | Speed + invariant | Size + invariant |
|---|---|---|---|
--version |
+47.7% | -4.1% | +44.5% |
--info |
+24.2% | -18.1% | +5.7% |
--help |
+47.0% | -3.1% | +43.7% |
build --help |
+47.9% | -0.8% | +43.4% |
restore --help |
+45.8% | -4.6% | +42.2% |
sdk check |
+8.5% | -16.4% | -1.5% |
- The PR more than doubles the native DLL at default settings: 20.60 MiB to 45.79 MiB.
OptimizationPreference=Sizerecovers about 9.5 MiB, but adds a largely fixed ~9–13 ms with normal globalization and ~12–16 ms with invariant globalization in this command matrix.- The fixed absolute cost makes the percentage regression look largest for parser-only commands and smaller for commands that do more work.
- Invariant globalization has little size benefit on Windows, but reduced
measured startup for
--infoandsdk checkby roughly 16–18%. --list-sdksand--list-runtimeswere excluded because they used managed fallback in the minimal benchmark harness.
These timings are process-launch microbenchmarks on one machine. They are useful for comparing these builds under the same conditions, not as universal absolute startup numbers.