Closed
Description
Tracking issue for further work on JS interop and multithreading.
Constituent part of #76956
Goals
- CPU intensive workloads on dotnet thread pool
- Allow user to start new managed threads using
new Thread
and join it. - Add new C# API for creating dedicated web workers with JS interop. Allow JS async/promises via external event loop.
- enable blocking
Task.Wait
andlock()
like APIs from C# user code on all threads or non-JS/UI threads- Current public API throws PNSE for it
- This is core part on MT value proposition.
- If people want to use existing MT code-bases, most of the time, the code is full of locks.
- People want to use existing desktop/server multi-threaded code as is.
- allow HTTP and WS C# APIs to be used from any thread despite underlying JS object affinity
- JSImport/JSExport interop in maximum possible extent.
- don't change/break single threaded build. †
Lower priority goals
- try to make it debugging friendly
- sync C# to async JS
- dynamic creation of new pthread
- implement crypto via
subtle
browser API - allow MonoVM to lazily download DLLs from the server, instead of during startup.
- implement synchronous APIs of the HTTP and WS clients. At the moment they throw PNSE.
- sync JS to async JS to sync C#
- allow calls to synchronous JSExport from UI thread (callback)
- don't prevent future marshaling of JS transferable objects, like streams and canvas.
- offload CPU intensive part of WASM startup to WebWorker, so that the pre-rendered (blazor) UI could stay responsive during Mono VM startup.
Non-goals
- interact with JS state on WebWorker of managed threads other than UI thread or dedicated
JSWebWorker
Design discussion and experiment
- Design discussion [browser][wasm] threads and JS interop designs#301
- test deputy/sidecar design with Blazor (in some limited way)
- [browser][MT] sidecar testing #92226
- [browser][MT] deputy testing (13) #93920
- [browser][MT] deputy testing (16) #94525
Depending on selected design
- call dispatch to/from UI thread
- call dispatch to/from JSWebWorker thread
- Make Promise -> Task marshaling ahead of call
- Make string marshaling non GC boundary breaching
- Make Array marshaling non GC boundary breaching
- dispatch calls with JS affinity to correct thread. Don't make the user responsible for it.
- Dynamic allocation of managed threads
- schedule disposal of
JSObject
proxy on correct thread later, so that it doesn't deadlock GC by dispatching to suspended thread - Make HTTP/WS clients dispatch more async
- Solve sync dispatch to HTTP/WS
- Blazor's
WebAssemblyDispatcher
more async, learn from feedback [blazor][wasm] Dispatch rendering to main thread aspnetcore#48991 - review Blazor legacy interop and JS interop
- [browser][MT] Add new test for multi-threadin SignalR in Blazor WBT #97085
Bugs
- [browser][MT] legacy JS interop needs GC boundaries on main thread too #90044
- [browser][mt] Running any Thread for longer than 5000 ms crashes runtime (Blazor) #86903
- [browser][MT] deadlock while disposing JS object from suspended thread #88663
- [browser][MT] Unhandled JS error #97546
- [browser][MT] GC deadlock #96190
- [browser][MT] Assert failed: Cannot find Promise for JSHandle -2 #98406
- [browser][MT] Depleted pthreadPoolSize #97913
- [browser][MT] Debugger timeout with deputy thread #98771
- [wasm][mt] Debugger test is using blocking calls in JS interop thread #97652
Memory growth, alignment
- [browser][mt] RangeError: Invalid atomic access index #96545
- [browser][MT] RangeError: offset is out of bounds #98630
- [browser][MT] RangeError: Invalid typed array length #98217
- [browser][MT] MutexTests - operation does not support unaligned accesses #96191
- [browser] RuntimeError: memory access out of bounds #96546
Broken tests
- [browser][mt] TCValidateAfterAddInvalidSchema.AddValid_Import_Include_Redefine #75132
- [browser][MT] ThreadStartException in System.Net.WebSockets.Client.Tests on WASM #93323
- [MT][browser]
System.Transactions
,System.Threading
timeouts #91541 - [browser][MT] System.Xml.Tests.TC_SchemaSet_Add_URL.v4 #75123
- [MT][browser]
WithExecutionMode
fails #91661 - [MT][browser]
customAttributeCount
fails #91597 - [MT][browser]
System.Threading.Tasks.Tests.TaskContinueWhenAnyTests.RunContinueWhenAnyTests
fails #91550 - [MT][browser]
System.Threading.Tasks.Tests.CancellationTokenTests.DerivedCancellationTokenSource
fails #91552 - [MT][browser]
CancellationTokenRegistration_DisposeAsyncWhileCallbackRunning_WaitsForCallbackToComplete
fails #91577 - [MT][browser]
ExceptionOnMoveNext
fails, wrong exception type #91581 - [MT][browser]
SimultaneousStopBreakTests
fails #91579 - [MT][browser]
TestParallelScheduler
fails, TaskScheduler.Default not used when no ParallelOptions are specified. #91582 - [MT][browser] MutexTests.AbandonExisting timeout #91547
- [browser][MT] CancellationTokenTests.DerivedCancellationTokenSource #94486
- [MT][browser]
TaskIDFromExternalContextTest
fails, Task has a negative ID #91583 - [MT][browser]
Wasm.Browser.Config.Sample
,Wasm.Browser.Config.Sample
fail #91676 - [browser][mt][hybrid] TestJapaneseCalendarDateParsing, PMDesignator_Get_ReturnsExpected_HybridGlobalization #95795
- [browser][MT] deadlock in BrowserWebSocket when used from multiple threads #96173
- [browser][MT] MutexTests - operation does not support unaligned accesses #96191
- [browser][mt] AsyncTransactionScopeTests.VerifyBYOTSyncTSNestedAsync - Value is not null #97513
- [browser][MT] Log_WritingScopes_LogsWithCorrectColorsWhenColorEnabled fails #97382
- [browser][MT] System.Net.WebSockets.Client.Tests.ConnectTest.ConnectAsync_CancellationRequestedInflightConnect_ThrowsOperationCanceledException #97092
- [browser][MT] various WebWorkerTest CI failures #96628
- [debugger][mt][browser] TestDebugUsingMultiThreadedRuntime times out #98110
- [mt][browser]
HttpClient_CancelInDifferentThread
failing with operation cancelled #98101 - [mt][browser] JsImportTaskEchoPendingResult fails #98035
- [mt][browser]
Wasm.Browser.EventPipe.Sample
fails #98026 - [browser][MT] MutexTests.NamedMutex_ThreadExitDisposeRaceTest #97968
- [browser][MT] WebWorkerTest.WaitAssertsOnJSInteropThreads #97914
- [browser][MT] System.Runtime.InteropServices.JavaScript.Tests.WebWorkerTest.ThreadingTimer #98216
- [browser][MT] System.Runtime.InteropServices.JavaScript.Tests.JSImportExportTest.JsImportTaskAwaitPendingResult #98219
- [browser][MT] System.Runtime.InteropServices.JavaScript.Tests.WebWorkerWebSocketTest.WebSocketClient_CancelInDifferentThread #98344
- [browser][MT] Some tests deadlock without -backgroundExec #99519
- [browser][MT] System.Threading.Tasks.Task.SpinThenBlockingWait(...) uses non supported API #44622
- [browser][MT] Deadlock in TaskCoverage.Coverage #99500
- [browser][MT] Deadlock in TCValidateAfterAddInvalidSchema.AddValid_Import_Include_Redefine #99499
- [browser][MT] SemaphoreSlimTests.RunSemaphoreSlimTest1_WaitAsync_NegativeCases deadlock #99501
- [browser][MT] deadlocks in JavaScript.Tests.WebWorkerTest #99951
- [browser] Unable to evaluate script: tab crashed #100275
- [browser]
Process terminated
assert handling at icall.c:6162 #100249
Nice to have
- more scenarios on Radek's perf bench
- Stop using ThreadlessXunitTestRunner [browser][mt] Stop using ThreadlessXunitTestRunner for MT unit tests #88763
- re-consider counting unsettled promises [wasm-mt] Land the webworker JSImport support #84489
- re-consider pending user
setTimeout
[browser][MT] Keep track of additional JS keepalive sources for worker threads #85052 - noisy emscripten [browser][mt] Upgrade emscripten #75625
- throw on blocking calls from UI [browser][mt] Do not allow blocking on the thread with JS interop: UI, JSWebWorker #76958
- blazor background startup Blazor webassembly startup speed and UI locking issue #65559
- console perf [browser][MT] emscripten_check_mailbox per console character #93603
- shutdown all threads/workers during
exit()
andabort()
- synchronous JS APIs on the UI thread and spin-wait
- other sync to async scenarios see above
- pthread pool size discussion [wasm-mt] Revisit the size of pthread pool for CI #75602
- [browser][MT] enable worker threads in sgen GC #98214
- [browser][hybrid] drop wrap_error_root,wrap_no_error_root #98365
- [browser][MT] asynch dispatch soundness #98309
- [browser][MT] enable jiterp #100273
Progress
- [browser][MT] enable timer tests #94217
- [browser][MT] enable MT PLINQ #94214
- [browser][MT] unify pthread pool size to 40 #94204
- [browser][MT] use portable timer #94180
- [browser] streamline Task/Promise marshalling - atttemp 2 #93648
- [browser][MT] more testing and cleanup #94466
- [browser] JSImport binding improvements #95177
- [browser] js string marshaling by value #95180
- [browser] eager allocation of Promise/Task result for async JSImport/JSExport #95411
- [browser] WS & HTTP clients more async #95483
- [browser][MT] enable finalizer thread, run most tests in threadpool #95783
- [browser][mt] dynamic thread create #95702
- [browser][MT] JSImport dispatch to target thread via JSSynchronizationContext #96319
- [browser][MT] fix CaptureContextFromParameter and SealJSImportCapturing #96504
- [blazor][wasm] Dispatch rendering to main thread (Net9) aspnetcore#52724
- [browser][MT] dispatch across threads via emscripten #97669
- [browser][MT] preparation for deputy #98298
- [browser] Move reflection from JS to C# #98391
- [browser][mt] drop managed keepalive from thread pool #99524
- [browser][MT] dedicated io thread #99422
- [browser][MT] Handling blocking wait #99833
- [browser][MT] fix nested synchronous JS interop call detection #99296
- [browser][MT] Marshal resolved/unresolved tasks separately #99347
- [browser][MT] Fix Promise cancelation #99397
- [browser][MT] smaller thread pool #100415
- [browser][MT] fix thread creation race with finalizer #100778
- [browser][MT] improve abort on web worker #100610
Future
- API for
JSWebWorker
with external loop and JS interop JSSynchronizationContext
for UI andJSWebWorker
threadsJSSynchronizationContext
forJSObject
proxy[UnsupportedOSPlatform]
ref assemblies [browser][MT] public API of threading, like new Thread vs PNSE #88147- [browser][mt] Propagate unhandled JS errors in JSWebWorker to the top level Task #76957
- [browser][MT] JS Interop should respect GC pauses #76963
- [browser][MT] make UI thread not managed/attached #100411
- [browser][MT] use code generator to get JSExport methods/ reduce reflection #98366
- [browser][MT] support for NodeJS #92853
- [browser][nodejs][MT] Worker script fails to start on NodeJS #87556
- [browser][MT] Switch to multi-threaded Emscripten VFS when it is available #76964