Investigate Blazor WebAssembly startup performance characteristics
Even when Blazor WebAssembly assets are cached, the time it takes for a Blazor WebAssembly app to initialize can be significant. We should investigate ways to further optimize Blazor WebAssembly initialization to reduce this startup time.
Some preliminary investigation suggests that Blazor-specific startup (everything that happens after the code in Program.cs starts executing) accounts for at least half the total initialization time.
We should:
- Add instrumentation to measure how long various initialization stages take
- Such stages include loading cached assets, initializing the .NET WebAssembly runtime, and many of the steps between the start of the app's entrypoint and the first interactive render
- Collect traces for Blazor-specific initialization code
- Given those results, determine what work can be done to minimize WebAssembly startup time
- Consider benchmarking daily builds so we can track these detailed performance measurements over time
Related issues:
- https://github.com/dotnet/aspnetcore/issues/42284
- https://github.com/dotnet/aspnetcore/issues/52154
Currently, when using Blazor in InteractiveAuto render mode, the application starts with Blazor Server on the initial load and transitions to WebAssembly once all DLLs are loaded and cached. However, on subsequent requests, it waits for WebAssembly to start, neglecting the benefits of Blazor Server.
To enhance performance and user experience, I suggest implementing a mechanism where the first page load or any subsequent refreshes always utilize Blazor Server, while booting WebAssembly in the background. This approach can mitigate concerns about WebAssembly startup performance, as we can improve it up to a certain extent.
Making this behavior configurable would provide flexibility. Users could choose to wait for WebAssembly to load when the cache is available or opt for Blazor Server on every initial request, even if WebAssembly is downloaded.
By implementing this approach, we can optimize the application's performance and provide users with a smoother transition to WebAssembly while still leveraging the benefits of Blazor Server where applicable.
Would love to hear thoughts and feedback on this proposal!
Bringing https://github.com/dotnet/aspnetcore/issues/31877 into the current milestone as @MackinnonBuck 's investigation leads us to believe that this work will bring substantial benefits to startup perf.
Here are some results from this investigation:
Add instrumentation to measure how long various initialization stages take... collect traces for Blazor-specific initialization code
By adding the following to the WebAssembly project's .csproj file:
<PropertyGroup>
<WasmProfilers>browser;</WasmProfilers>
<WasmBuildNative>true</WasmBuildNative>
</PropertyGroup>
...and adding the following to the webAssembly options in Blazor.start():
configureRuntime: (builder) => {
builder.withConfig({
browserProfilerOptions: {},
});
}
...a recording can be taken in the browser's dev tools "performance" tab and a flame graph will show how long each procedure takes.
Given those results, determine what work can be done to minimize WebAssembly startup time
One of the main contributors to startup time was reflection performed during JSON serialization. This indicated that using the STJ source generator may yield performance benefits.
Consider benchmarking daily builds so we can track these detailed performance measurements over time
In addition to existing Blazor WebAssembly standalone perf tests, we added automated Lighthouse tests earlier this year to see how changes like this affect Lighthouse metrics.
After introducing a change that utilized the STJ source generator during WebAssembly startup, we noticed a WebAssembly startup time improvement of 15-30%. These numbers may vary for larger apps, or apps that do significant work in user code during startup.
Finding a way to eliminate JSON serialization altogether during startup may result in further improvement of startup time (I would conservatively estimate an additional 15% improvement, possibly higher for Blazor Web scenarios because it performs more serialization on startup).
Closing this issue out since the investigation is complete, and we have taken some steps to improve WebAssembly startup performance. We can open other issues to track additional improvements to WebAssembly startup.