Multithreading
Takeaways:
- Performance can be achieved by parallelizing tasks.
- Native: Tasks submitted to the thread pool are executed immediately[citation needed].
- WASM: Tasks submitted to the thread pool are executed when control returns to the browser.
- WASM: Since tasks will never run until the main thread returns, the main thread cannot wait for tasks to complete.
- Github issue(s): amethyst#2191
Amethyst uses rayon
to manage a thread pool, and parallel processing is achieved by submitting tasks to that pool.
Dispatcher
Native
In native applications, parallel execution is enabled by default.
When tasks are submitted to the thread pool, they are executed immediately.
Parallel execution control flow
sequenceDiagram participant main participant #nbsp; participant W0 participant W1 participant W2 main ->>+ #nbsp;: dispatch_par() rect rgba(0, 100, 255, .2) #nbsp; -->>+ W2: 🎶 Play Music#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp; #nbsp; -->>+ W0: 🎮 Device#nbsp;#nbsp;#nbsp;#nbsp; #nbsp; -->>+ W1: 🌐 Network #nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp; W0 -->>- #nbsp;: #nbsp; W1 -->>- #nbsp;: #nbsp; W2 -->>- #nbsp;: #nbsp; #nbsp; -->>+ W2: 📦 Load Assets#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp; Note left of W2: 📦 Task #nbsp; -->>+ W1: 📄 Read File#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp;#nbsp; W2 -->>- #nbsp;: #nbsp; W1 -->>- #nbsp;: #nbsp; #nbsp; -->>+ W0: 📡 Position#nbsp;#nbsp;#nbsp; W0 -->>- #nbsp;: #nbsp; W1 -->+ W1: 📦 Asset Load Task end #nbsp; ->>- main: #nbsp; %% Asset Load Task end W1 -->- W1: #nbsp; main ->>+ #nbsp;: dispatch_thread_local() rect rgba(180, 0, 220, .2) #nbsp; -->>+ main: 🖌️ Render main -->>- #nbsp;: #nbsp; #nbsp; -->>+ main: 🎨 Load Textures main -->>- #nbsp;: #nbsp; end #nbsp; ->>- main: #nbsp;
WASM
When adding WASM support, sequential execution is used.
If we tried to use parallel execution, tasks that are submitted to the thread pool are queued. They will only run when control has been returned to the browser, as the browser will only send the tasks (as messages) to each web worker when it has control. This is a problem because the main thread would be waiting for all the tasks to complete, when in fact nothing is running.
Sequential execution control flow
sequenceDiagram participant main participant #nbsp; participant W0; participant W1; participant W2; main ->>+ #nbsp;: dispatch_seq() rect rgba(0, 100, 255, .2) #nbsp; -->>+ main: 🎮 Device main -->>- #nbsp;: #nbsp; #nbsp; -->>+ main: 🌐 Network main -->>- #nbsp;: #nbsp; #nbsp; -->>+ main: 📦 Load Assets Note left of #nbsp;: 📦 Task main -->>- #nbsp;: #nbsp; #nbsp; -->>+ main: 📄 Read File main -->>- #nbsp;: #nbsp; #nbsp; -->>+ main: 📡 Position main -->>- #nbsp;: #nbsp; #nbsp; -->>+ main: 🎶 Play Music main -->>- #nbsp;: #nbsp; end #nbsp; ->>- main: #nbsp; main ->>+ #nbsp;: dispatch_thread_local() rect rgba(180, 0, 220, .2) #nbsp; -->>+ main: 🖌️ Render main -->>- #nbsp;: #nbsp; #nbsp; -->>+ main: 🎨 Load Textures main -->>- #nbsp;: #nbsp; end #nbsp; ->>- main: #nbsp; W0 -->+ W0: 📦 Asset Load Task %% Asset Load Task end W0 -->- W0: #nbsp;