| 1 |
--- |
| 2 |
title: Weak system ordering with chain_weak |
| 3 |
authors: ["@JMS55"] |
| 4 |
pull_requests: [25128] |
| 5 |
--- |
| 6 |
|
| 7 |
Ordering large groups of systems with `.chain()` is convenient, but it can be |
| 8 |
overly strict. If system set `X` is chained before system set `Y`, every system |
| 9 |
in `X` must finish before *any* system in `Y` can start, even when the systems |
| 10 |
involved never touch the same data. This often leaves worker threads idle while they |
| 11 |
wait for a handful of stragglers at the end of a system set, a pattern that shows up |
| 12 |
frequently in the render world. |
| 13 |
|
| 14 |
The new `chain_weak()`, `before_weak()`, and `after_weak()` functions provide a looser alternative. |
| 15 |
Like their regular counterparts, they request an ordering between successive elements, however that |
| 16 |
ordering is only kept between systems whose data accesses actually conflict. Systems that don't |
| 17 |
conflict are left unordered and may run in any order, including in parallel. |
| 18 |
|
| 19 |
```rust |
| 20 |
schedule.configure_sets( |
| 21 |
( |
| 22 |
ExtractCommands, |
| 23 |
PrepareMeshes, |
| 24 |
CreateViews, |
| 25 |
Specialize, |
| 26 |
PrepareViews, |
| 27 |
Queue, |
| 28 |
PhaseSort, |
| 29 |
Prepare, |
| 30 |
Render, |
| 31 |
Cleanup, |
| 32 |
PostCleanup, |
| 33 |
) |
| 34 |
.chain_weak(), |
| 35 |
); |
| 36 |
``` |
| 37 |
|
| 38 |
When two weakly-ordered systems actually conflict on their data access, a normal |
| 39 |
ordering is kept between them, so the earlier one still runs first. Two |
| 40 |
systems that conflict only through a non-conflicting system between them in the chain |
| 41 |
stay ordered as well. Non-conflicting systems, however, are left free to run in any |
| 42 |
order and overlap for increased parallelism! |
| 43 |
|
| 44 |
Two kinds of system are treated as always conflicting, so their ordering is always |
| 45 |
kept: an earlier system that produces deferred effects such as `Commands` (so the |
| 46 |
later system observes them, with an `ApplyDeferred` sync point inserted as usual), and |
| 47 |
exclusive systems (which cannot overlap anything regardless). |
| 48 |
|
| 49 |
Because the scheduler can only see accesses it tracks, dependencies expressed |
| 50 |
through interior mutability on read-only accesses, global state, or other untracked |
| 51 |
methods are **not** respected. Use `chain_weak` only when your systems don't rely |
| 52 |
on such hidden ordering, otherwise stick with `chain`. |