Description
Issue to capture data, ideas, etc. regarding improving the DX performance of the new dotnet run file.cs
feature. Specific work item issues can be added as sub-issues to this epic.
Some baseline numbers
Windows & WSL2 numbers measured on the same machine. Mac numbers measured on an M4 Mac Mini. Both Windows & Mac machines enrolled in corporate device management.
Command | OS | Time | Notes |
---|---|---|---|
dotnet --list-sdks |
Windows | ~12-20ms | No managed runtime involved so extremely fast listing of SDK directories in known location |
dotnet --list-sdks |
Ubuntu via WSL2 | ~5ms | |
dotnet --list-sdks |
macOS | ~17-20ms | |
dotnet run --help |
Windows | ~200ms | Loads the CLI and dispatches to the run command. Basically as fast as an invocation of dotnet run can be. Anything we can do to reduce this should improve the DX of dotnet run file.cs too. |
dotnet run --help |
Ubuntu via WSL2 | ~112ms | |
dotnet run --help |
macOS | ~144ms | |
dotnet exec hello.dll |
Windows | ~32ms | Full run of a built hello world console app (default Debug configuration). Anything more than this is DX overhead. |
dotnet exec hello.dll |
Ubuntu via WSL2 | ~31ms | Interestingly this is the only case where the number is basically the same between Windows and Ubuntu |
dotnet exec hello.dll |
macOS | ~54ms | This was consistently slower than launching on my Windows/WSL2 machine |
Windows vs. Linux (WSL)
I did some comparisons of running dotnet run hello.cs
on various Windows 11 machines (both Intuned and not Intuned, desktops and laptops) vs. running it in a WSL2 Ubuntu instance on those same machines. In each case, the .NET CLI was installed into the Linux instance and the test C# files were in the Linux file system directly rather than accessed via the host.
In all cases, running dotnet run hello.cs
in the WSL instance was significantly faster, usually around 40-50% faster but sometimes even more. On my laptop It usually took around 2-2.5 seconds in Windows, and in WSL it took only 1.1-1.2 seconds. On my desktops the numbers were more like Windows 1.5 seconds, WSL 1.0 seconds.
This pattern was consistent whether running with real-time antivirus inspection enabled or disabled (either via directory exclusions or by completely disabling it).
Not sure what action we can take other than profiling to help isolate the differences but the data seemed interesting to record.
Build vs. no-build
The overhead of performing a build (i.e. using MSBuild) during dotnet run hello.cs
is significant. Directly comparing dotnet run hello.cs
to dotnet run hello.cs --no-build
results in times like the following (all measurements taken on the same machine):
Command | OS | Time |
---|---|---|
dotnet run file.cs |
Windows | ~1.5s |
dotnet run file.cs --no-build |
Windows | ~630ms |
dotnet run file.cs |
Ubuntu via WSL2 | ~830ms |
dotnet run file.cs --no-build |
Ubuntu via WSL2 | ~330ms |
It seems it will be extremely beneficial to explore ways in which we can speed up the build step, or completely avoid it when possible, given the more scoped set of changes that might occur between runs of a specific C# file, e.g.:
- Enabling of the MSBuild server is planned later in the .NET 10 cycle & could improve build times
- Caching of the RAR task outputs has been discussed and could improve build times
- runfile could completely avoid running build if there are no implicit build files and no C# file directives (i.e.
#:sdk
and#:package
) as the set of inputs to the compiler is fixed (e.g. at CLI build time) and could be invoked directly - runfile could implement up-to-date checks (modified time stamps, content hashes) on build-effecting inputs like implicit build files, C# files, and C# file directives and when no build-impacting changes are detected directly invoke the compiler using cached arguments from the previous run.
- Adding or deleting a C# file would likely need to be considered a change that requires re-invoking build as globs are evaluated as part of the build, but non-directive changes to C# files should be fine