-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[wasm-mt] Use asset loading for dotnet.worker.js; update WasmAppBuild…
…er (#73697) Enables using asset loading to get the `dotnet.worker.js` file that provides the emscripten pthread worker code. Also allows specifying the number of pre-allocated workers that will be created at startup using MSBuild properties. Fixes #68509 and fixes #68397 and fixes #72606 - Override Emscripten `PThread.allocateUnusedWorker` We want to use our own allocateUnusedWorker because we want to load `dotnet.worker.js` using our asset loading machinery. Unfortunately, Emscripten first calls allocateUnusedWorker very early (from `PThread.init`) to pre-allocate the pthread worker pool. So we set Emscripten's own pthread worker pool to size 0 and make our own. This requires calling `loadWasmModuleToWorker` during our startup because Emscripten deletes their code that normally does it (in "receiveInstance" in "createWasm" in "emscripten/src/preamble.js") when the pthread pool size is 0. Also added a pthreadPoolSize field to MonoConfig to allow specifying the initial pthread pool size in mono-config.json - Add `IncludeThreadsWorker` and `PThreadPoolSize` props to WasmAppBuilder `IncludeThreadsWorker` adds the `"js-module-threads"` asset to the `mono-config.json` `PThreadPoolSize` can be -1 or >=0 to specify the number of workers that will be pre-allocated at startup for the pthread worker pool. -1 means use the default compiled into `dotnet.js` - Reorganize the pthreads TS code by moving `Internals` (access API that digs through Emscripten's pthreads implementation) to its own module. And add types. - Replace emscripten's `allocateUnusedWorker` function with our own that goes through the asset loading API. - Update samples - Set up console proxying for the workers. This is done by sending a message from the main thread to the pthread workers with the current `MonoConfig` on our dedicated channel. (This means the proxying is setup asynchronously, so if the worker is busy before it receives the message, it may not start redirecting messages right away). --- * [wasm-mt] Override Emscripten PThread.allocateUnusedWorker We want to use our own allocateUnusedWorker because we want to load `dotnet.worker.js` using our asset loading machinery. Unfortunately, Emscripten first calls allocateUnusedWorker very early (from `PThread.init`) to pre-allocate the pthread worker pool. So we set Emscripten's own pthread worker pool to size 0 and make our own. This requires calling `loadWasmModuleToWorker` during our startup because Emscripten deletes their code that normally does it (in "receiveInstance" in "createWasm" in "emscripten/src/preamble.js") when the pthread pool size is 0. Also added a pthreadPoolSize field to MonoConfig to allow specifying the initial pthread pool size in mono-config.json * Add IncludeThreadsWorker and PThreadPoolSize props to WasmAppBuilder IncludeThreadsWorker adds the js-module-threads asset to the mono-config PThreadPoolSize can be -1 or >=0 to specify the number of workers that will be pre-allocated at startup for the pthread worker pool. -1 means use the default compiled into dotnet.js * Move emscripten PThread internals access to a separate module and add types * Load js-module-threads asset in replacement allocateUnusedWorker * Update samples to explicitly enable threading / perftracing Makes the WasmAppBuilder include the threads worker module * tighten up Internals types * apply review feedback * fix import * Apply suggestions from code review * proxy pthread worker messages to websocket, if enabled use a new MonoThreadMessageApplyMonoConfig message to send the MonoConfig from the main thread to each worker when the workers set up the communication channel to the main thread. then if the diagnosticTracing property is true, redirect the worker console logging to a websocket. Fixes #72606 Co-authored-by: Marek Fišera <[email protected]> Co-authored-by: Ankit Jain <[email protected]>
- Loading branch information
1 parent
99abf51
commit 88ba045
Showing
20 changed files
with
286 additions
and
43 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
76 changes: 76 additions & 0 deletions
76
src/mono/wasm/runtime/pthreads/shared/emscripten-internals.ts
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
import { Module } from "../../imports"; | ||
import { pthread_ptr } from "./types"; | ||
|
||
/** @module emscripten-internals accessors to the functions in the emscripten PThreads library, including | ||
* the low-level representations of {@linkcode pthread_ptr} thread info structs, etc. | ||
* Additionally, note that some of these functions are replaced by {@linkcode file://./emscripten-replacements.ts}. | ||
* These have a hard dependency on the version of Emscripten that we are using and may need to be kept in sync with | ||
* {@linkcode file://./../../../emsdk/upstream/emscripten/src/library_pthread.js} | ||
*/ | ||
|
||
// This is what we know about the Emscripten PThread library | ||
interface PThreadLibrary { | ||
unusedWorkers: Worker[]; | ||
pthreads: PThreadInfoMap; | ||
allocateUnusedWorker: () => void; | ||
loadWasmModuleToWorker: (worker: Worker, onFinishedLoading?: (worker: Worker) => void) => void; | ||
} | ||
|
||
interface EmscriptenPThreadInfo { | ||
threadInfoStruct: pthread_ptr; | ||
} | ||
|
||
/// N.B. emscripten deletes the `pthread` property from the worker when it is not actively running a pthread | ||
interface PThreadWorker extends Worker { | ||
pthread: EmscriptenPThreadInfo; | ||
} | ||
|
||
interface PThreadObject { | ||
worker: PThreadWorker; | ||
} | ||
|
||
interface PThreadInfoMap { | ||
[key: pthread_ptr]: PThreadObject | undefined; | ||
} | ||
|
||
|
||
function isRunningPThreadWorker(w: Worker): w is PThreadWorker { | ||
return (<any>w).pthread !== undefined; | ||
} | ||
|
||
/// These utility functions dig into Emscripten internals | ||
const Internals = { | ||
get modulePThread(): PThreadLibrary { | ||
return (<any>Module).PThread as PThreadLibrary; | ||
}, | ||
getWorker: (pthread_ptr: pthread_ptr): PThreadWorker | undefined => { | ||
// see https://github.com/emscripten-core/emscripten/pull/16239 | ||
return Internals.modulePThread.pthreads[pthread_ptr]?.worker; | ||
}, | ||
getThreadId: (worker: Worker): pthread_ptr | undefined => { | ||
/// See library_pthread.js in Emscripten. | ||
/// They hang a "pthread" object from the worker if the worker is running a thread, and remove it when the thread stops by doing `pthread_exit` or when it's joined using `pthread_join`. | ||
if (!isRunningPThreadWorker(worker)) | ||
return undefined; | ||
const emscriptenThreadInfo = worker.pthread; | ||
return emscriptenThreadInfo.threadInfoStruct; | ||
}, | ||
allocateUnusedWorker: (): void => { | ||
/// See library_pthread.js in Emscripten. | ||
/// This function allocates a new worker and adds it to the pool of workers. | ||
/// It's called when the pool of workers is empty and a new thread is created. | ||
Internals.modulePThread.allocateUnusedWorker(); | ||
}, | ||
getUnusedWorkerPool: (): Worker[] => { | ||
return Internals.modulePThread.unusedWorkers; | ||
}, | ||
loadWasmModuleToWorker: (worker: Worker, onFinishedLoading: () => void): void => { | ||
Internals.modulePThread.loadWasmModuleToWorker(worker, onFinishedLoading); | ||
} | ||
}; | ||
|
||
|
||
export default Internals; |
44 changes: 44 additions & 0 deletions
44
src/mono/wasm/runtime/pthreads/shared/emscripten-replacements.ts
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
import MonoWasmThreads from "consts:monoWasmThreads"; | ||
import { PThreadReplacements } from "../../types"; | ||
import { afterLoadWasmModuleToWorker } from "../browser"; | ||
import { afterThreadInitTLS } from "../worker"; | ||
import Internals from "./emscripten-internals"; | ||
import { resolve_asset_path } from "../../assets"; | ||
import { mono_assert } from "../../types"; | ||
import { runtimeHelpers } from "../../imports"; | ||
|
||
/** @module emscripten-replacements Replacements for individual functions in the emscripten PThreads library. | ||
* These have a hard dependency on the version of Emscripten that we are using and may need to be kept in sync with | ||
* {@linkcode file://./../../../emsdk/upstream/emscripten/src/library_pthread.js} | ||
*/ | ||
|
||
export function replaceEmscriptenPThreadLibrary(replacements: PThreadReplacements): void { | ||
if (MonoWasmThreads) { | ||
const originalLoadWasmModuleToWorker = replacements.loadWasmModuleToWorker; | ||
replacements.loadWasmModuleToWorker = (worker: Worker, onFinishedLoading?: (worker: Worker) => void): void => { | ||
originalLoadWasmModuleToWorker(worker, onFinishedLoading); | ||
afterLoadWasmModuleToWorker(worker); | ||
}; | ||
const originalThreadInitTLS = replacements.threadInitTLS; | ||
replacements.threadInitTLS = (): void => { | ||
originalThreadInitTLS(); | ||
afterThreadInitTLS(); | ||
}; | ||
// const originalAllocateUnusedWorker = replacements.allocateUnusedWorker; | ||
replacements.allocateUnusedWorker = replacementAllocateUnusedWorker; | ||
} | ||
} | ||
|
||
/// We replace Module["PThreads"].allocateUnusedWorker with this version that knows about assets | ||
function replacementAllocateUnusedWorker(): void { | ||
if (runtimeHelpers.diagnosticTracing) | ||
console.debug("MONO_WASM: replacementAllocateUnusedWorker"); | ||
const asset = resolve_asset_path("js-module-threads"); | ||
const uri = asset.resolvedUrl; | ||
mono_assert(uri !== undefined, "could not resolve the uri for the js-module-threads asset"); | ||
const worker = new Worker(uri); | ||
Internals.getUnusedWorkerPool().push(worker); | ||
} |
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,8 @@ | ||
{ | ||
"extends": "../../tsconfig.shared.json" | ||
"extends": "../../tsconfig.shared.json", | ||
"include": [ | ||
"../../**/*.ts", | ||
"../../**/*.d.ts" | ||
] | ||
|
||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
/// pthread_t in C | ||
export type pthread_ptr = number; |
This file contains 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
Oops, something went wrong.