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;