Skip to content

Conversation

@pavelsavara
Copy link
Member

@pavelsavara pavelsavara commented Jan 18, 2026

  • make ST work also for CoreCLR flavor
  • throw method of unsupported blocking .Wait()
  • simplify ProcessorCount subbing

@pavelsavara pavelsavara added this to the 11.0.0 milestone Jan 18, 2026
@pavelsavara pavelsavara self-assigned this Jan 18, 2026
@pavelsavara pavelsavara added arch-wasm WebAssembly architecture area-System.Threading size-reduction Issues impacting final app size primary for size sensitive workloads os-browser Browser variant of arch-wasm labels Jan 18, 2026
@dotnet-policy-service dotnet-policy-service bot added the linkable-framework Issues associated with delivering a linker friendly framework label Jan 18, 2026
@pavelsavara pavelsavara changed the title [browser] improve trimming [browser][ST] improve Wait trimming Jan 18, 2026
@pavelsavara pavelsavara marked this pull request as ready for review January 19, 2026 19:45
Copilot AI review requested due to automatic review settings January 19, 2026 19:45
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves trimming for single-threaded (ST) WebAssembly builds by making the trimming work for both CoreCLR and Mono flavors, adding guards to trim code after unsupported blocking operations, and simplifying the ProcessorCount substitution approach.

Changes:

  • Replaced ILLink XML substitution for ProcessorCount with inline conditional compilation
  • Added FEATURE_SINGLE_THREADED guards before blocking operations to enable better code trimming
  • Extended single-threaded support from browser-only to both browser and WASI platforms

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
ILLink.Substitutions.wasm.singlethread.xml Removed - ProcessorCount substitution now handled inline
System.Private.CoreLib.csproj (Mono) Removed reference to deleted substitution file
Parallel.cs Added FEATURE_SINGLE_THREADED guard before WaitAll blocking operation
System.Threading.Tasks.Parallel.csproj Added FeatureSingleThread property and FEATURE_SINGLE_THREADED define
Task.cs Added guards before blocking wait operations in SpinThenBlockingWait and WaitAnyCore
FutureFactory.cs Added guard before RegisterWaitForSingleObject blocking operation
LowLevelLock.cs Added guard before blocking monitor acquire
Environment.cs Moved ProcessorCount property inside conditional compilation for better trimming
NativeRuntimeEventSource.Threading.cs Added early return for browser in ThreadPoolIOEnqueue
NativeRuntimeEventSource.Threading.NativeSinks.cs Added PlatformNotSupportedException for browser in ThreadPoolIOEnqueue
SystemdNotifier.cs Added IsBrowser check to existing WASI platform check
XmlDocumentDecryptor.cs Added IsBrowser check to existing WASI platform check
Thread.CoreCLR.cs Added early return for browser in SpinWait
System.Private.CoreLib.csproj (CoreCLR) Added feature flags, defines, and browser platform support for CA1416

Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please share some number for how much this saves?

@jkoritzinsky
Copy link
Member

If the goal is to trim the wait subsystem, would it be worthwhile to provide an alternative implementation of the wait subsystem APIs for the single-threaded scenario that throw when they'd need to wait?

Then we wouldn't have this complicated dance to avoid rooting the waiting paths.

@pavelsavara
Copy link
Member Author

Here my goal was mostly fail instead of spin-deadlock.
I saw it with CoreCLR when working on HTTP unit tests.

Could you please share some number for how much this saves?

This PR alone would not be enough to cut all calls to all flavors of .Wait()
I have few more open PR which would be necessary.
The others are #123326 and #123357.
And maybe not even that would be enough to trim the wait subsystem.

If the goal is to trim the wait subsystem, would it be worthwhile to provide an alternative implementation of the wait subsystem APIs for the single-threaded scenario that throw when they'd need to wait?

This is interesting idea. When we reach the point when we compare size between Net11 Mono vs Net12 CoreCLR, there would be much bigger motivation to work on it.

@pavelsavara pavelsavara removed size-reduction Issues impacting final app size primary for size sensitive workloads linkable-framework Issues associated with delivering a linker friendly framework labels Jan 20, 2026
@dotnet-policy-service dotnet-policy-service bot added the linkable-framework Issues associated with delivering a linker friendly framework label Jan 20, 2026
@jkotas
Copy link
Member

jkotas commented Jan 20, 2026

unfortunately Thread.ThrowIfSingleThreaded(); is not "inlined" and understood by ILLink

Can you fix this by marking it with [DoesNotReturn] when FEATURE_SINGLE_THREADED is defined?

@pavelsavara
Copy link
Member Author

pavelsavara commented Jan 21, 2026

Can you fix this by marking it with [DoesNotReturn] when FEATURE_SINGLE_THREADED is defined?

That didn't help.

I also tried [MethodImpl(MethodImplOptions.AggressiveInlining)] earlier and that didn't help either.

Anyway, right now I need it to throw, we can re-focus on trimming later

- move ThrowIfSingleThreaded after argument validation and only on actually blocking path
@pavelsavara
Copy link
Member Author

/ba-g failure is #123442

@pavelsavara
Copy link
Member Author

I enabled those as smoke test on CoreCLR/wasm.

Log

[12:15:28] info: === TEST EXECUTION SUMMARY ===
[12:15:28] info: Tests run: 652 Passed: 311 Inconclusive: 0 Failed: 0 Ignored: 0 Skipped: 341
[12:15:28] info: 
[12:15:28] info: test-main.js exiting WasmTestRunner.dll System.Threading.Tasks.Tests.dll after 0.11008333333333334 minutes with result 0 and linear memory 193331200 bytes

Log

[12:18:58] info: === TEST EXECUTION SUMMARY ===
[12:18:58] info: Tests run: 632 Passed: 545 Inconclusive: 0 Failed: 0 Ignored: 0 Skipped: 87
[12:18:58] info: 
[12:18:58] info: test-main.js exiting WasmTestRunner.dll System.Threading.Tests.dll after 2.592633333333333 minutes with result 0 and linear memory 193331200 bytes

@pavelsavara pavelsavara enabled auto-merge (squash) January 22, 2026 14:33
@pavelsavara pavelsavara merged commit a118808 into dotnet:main Jan 22, 2026
149 of 151 checks passed
@pavelsavara pavelsavara deleted the browser_trimming branch January 22, 2026 14:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-wasm WebAssembly architecture area-System.Threading linkable-framework Issues associated with delivering a linker friendly framework os-browser Browser variant of arch-wasm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants