src/MudBlazor.Benchmarks/README.md
Performance benchmarking suite for MudBlazor's ParameterState framework using BenchmarkDotNet.
This project contains comprehensive benchmarks to measure and optimize the performance of the ParameterState system in MudBlazor. The ParameterState framework is central to MudBlazor's rendering and parameter-binding system, used by hundreds of components throughout the library.
dotnet run -c Release --project src/MudBlazor.Benchmarks/MudBlazor.Benchmarks.csproj
# Basic operations (register, lifecycle, SetValueAsync)
dotnet run -c Release --project src/MudBlazor.Benchmarks/MudBlazor.Benchmarks.csproj -- --basic
# Large-scale scenarios (100, 1000 parameters)
dotnet run -c Release --project src/MudBlazor.Benchmarks/MudBlazor.Benchmarks.csproj -- --largescale
# Comparer strategies
dotnet run -c Release --project src/MudBlazor.Benchmarks/MudBlazor.Benchmarks.csproj -- --comparer
Measures performance of fundamental ParameterState operations:
Stress tests with large parameter counts:
Compares different comparer strategies:
The benchmarks use a synthetic container that simulates Blazor component lifecycle without depending on the Blazor runtime. This allows isolated performance testing of ParameterState operations.
The container properly simulates the Blazor lifecycle as documented at https://blazor-university.com/components/component-lifecycles/:
First Render (new instance):
SetParametersAsync - receives parametersbase.SetParametersAsync(parameters) - assigns [Parameter] propertiesOnInitialized - called once for new instancesOnParametersSet - called after OnInitializedRe-Render (existing instance):
SetParametersAsync - receives parametersbase.SetParametersAsync(parameters) - assigns [Parameter] propertiesOnParametersSet - called directly (OnInitialized is skipped)Based on code analysis and benchmark results, the following areas have been identified as potential optimization targets:
Comparer Invocation
ParameterEqualityComparerSwappable<T>.Equals() invokes UnderlyingComparer() on every equality checkSetValueAsync and OnParametersSetDictionary Lookups
FrozenDictionary used in ParameterScopeContainer is already optimizedSelectMany operations in ParameterContainer.SetParametersAsync iterate all parametersLazy Initialization
RegisterParameterBuilder<T> uses Lazy<T> for parameter state creationParameterScopeContainer uses Lazy<FrozenDictionary<>> for parametersEquality Comparisons
SetValueAsync: _comparer.Equals(_value, value)OnParametersSet: _comparer.Equals(_lastValue, currentParameterValue)HasParameterChanged: comparer.Equals(...) via ParameterView extensionEventCallback Invocation
eventCallback.InvokeAsync(value) when HasDelegate is trueParameterView Extensions
HasParameterChanged performs manual parameter lookupCache Comparer Results
Reduce Allocations
ParameterChangedEventArgs<T> created on every changeOptimize Batch Updates
ToHashSet(ParameterHandlerUniquenessComparer.Default) allocatesInline Fast Paths
SetValueAsync when value hasn't changed (already done)OnParametersSet when no handlers exist[MemoryDiagnoser]: Track allocations, not just CPU time[Benchmark(Baseline = true)] for relative comparisonsWhen adding new benchmarks:
[MemoryDiagnoser] to track allocations[Params(...)] for varying test sizes