[blazor][wasm] optimize away locks in hot render code#65900
Closed
[blazor][wasm] optimize away locks in hot render code#65900
Conversation
…leThreadedLockScope Replace lock statements with SingleThreadedLockScope in Renderer.cs and RendererSynchronizationContext.cs. On browser targets (single-threaded WASM), OperatingSystem.IsBrowser() is a trimmer-recognized feature switch, allowing the trimmer to strip all Monitor.Enter/Exit calls since they are pure overhead without multithreading. Co-authored-by: pavelsavara <271576+pavelsavara@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/aspnetcore/sessions/0c886500-ff3d-4c5b-a6a9-49a7898252b6
…on-nullable Co-authored-by: pavelsavara <271576+pavelsavara@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/aspnetcore/sessions/0c886500-ff3d-4c5b-a6a9-49a7898252b6
Copilot created this pull request from a session on behalf of
pavelsavara
March 22, 2026 20:48
View session
…leThreadedLockScope Co-authored-by: pavelsavara <271576+pavelsavara@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/aspnetcore/sessions/da00e8e5-acb2-479f-9133-424eaf82bd7f
Contributor
There was a problem hiding this comment.
Pull request overview
This PR introduces a SingleThreadedLockScope helper intended to elide Monitor/lock overhead on single-threaded WebAssembly (browser) builds, and switches key renderer/sync-context critical sections from lock to this new scope.
Changes:
- Add
SingleThreadedLockScoperef struct that conditionally avoids taking a monitor lock on browser targets. - Replace several
lock (...) { ... }blocks withusing (new SingleThreadedLockScope(...)) { ... }in renderer synchronization and disposal paths. - Add a TODO note to eventually use a multithreading-aware runtime feature check.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/Components/Components/src/Rendering/SingleThreadedLockScope.cs | Adds a lock-scope abstraction that can become a no-op on browser targets for trimming/perf. |
| src/Components/Components/src/Rendering/RendererSynchronizationContext.cs | Replaces lock (_lock) with SingleThreadedLockScope to reduce overhead on WASM. |
| src/Components/Components/src/RenderTree/Renderer.cs | Replaces lock (_lockObject) with SingleThreadedLockScope in dispose-related thread-safety paths. |
src/Components/Components/src/Rendering/RendererSynchronizationContext.cs
Show resolved
Hide resolved
This was referenced Mar 23, 2026
Member
|
@copilot update the PR description to match the change |
Contributor
Author
Updated the PR description to reflect the full scope of changes: new |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Eliminate
lock/Monitoroverhead on single-threaded WASM (browser) targets where no thread contention is possible, usingOperatingSystem.IsBrowser()as a trimmer-recognized feature switch.Description
On single-threaded WASM,
lock/Monitor.Enter/Monitor.Exitare pure overhead — no thread contention exists.OperatingSystem.IsBrowser()is a trimmer-recognized feature switch, so guarding behind it lets the trimmer strip the synchronization code entirely from browser builds.Changes
SingleThreadedLockScope(src/Components/Components/src/Rendering/SingleThreadedLockScope.cs) — aref structwith pattern-based disposal that conditionally acquires aMonitorlock only when!OperatingSystem.IsBrowser(). Zero-cost on WASM after trimming.Renderer.cs— Replacedlock (_lockObject)withusing (new SingleThreadedLockScope(_lockObject))in 3 sites withinDispose(bool)andDisposeAsync().RendererSynchronizationContext.cs— Replacedlock (_lock)withusing (new SingleThreadedLockScope(_lock))in 5 sites:InvokeAsync(Action),InvokeAsync<TResult>,Post,Send, andSendIfQuiescedOrElsePost.// TODO use RuntimeFeature.IsMultithreadingSupportedreferencing [API] RuntimeFeature.IsMultithreadingSupported runtime#124603, to migrate to a more precise guard once the API ships (which will also handle multithreaded WASM correctly).