DOTS//CORE local · not synced

m02 · Systems · drill · 45 min

Remove every sync point from a system that must create and destroy

Why this is a drill and not a lab

The sync-point lab measured what a structural change costs. It gave you the number and the mechanism. What it did not do is put you in front of code that is already wrong and ask you to fix it without changing what it does.

That is the actual job. Nobody hands you a greenfield spawn system; they hand you one that works, stutters, and cannot be broken. The constraint that makes this hard is not performance — it is identical observable behaviour, which forbids the easy wins.

The starting point

Build or obtain a system with this shape — deliberately naive, and deliberately plausible:

  • A spawn system that, each frame, decides how many entities to create and creates them immediately via EntityManager.
  • A despawn system that finds entities whose health has dropped to zero and destroys them immediately, also via EntityManager.
  • A damage system between the two that writes health, and occasionally adds a Dying tag.
  • All three in SimulationSystemGroup, in that order.

Get it running with a few thousand entities and enough churn that the stalls are visible in the Profiler. Measure the baseline before touching anything — the sync-point lab’s probe is the right instrument, and without that number your “improvement” is a feeling.

The conflicts, named

| Constraint | The shortcut it closes | |---|---| | Behaviour must be unchanged | Fixing the stutter by spawning less, which is not the exercise | | No structural change in a job, no early complete | Completing a job to do the change “safely” on the main thread — the same barrier, hidden | | No doing less work | Reducing churn instead of reducing barriers | | Name the group for each barrier | Moving playback somewhere quiet and hoping | | No mid-frame count polling | Reading EntityManager state to decide, which forces the sync you are removing |

The third and fifth are the ones people trip on. Reducing spawn rate makes the profile look better and teaches nothing. Polling entity counts to decide what to enqueue reintroduces the stall through a side door that does not look like a structural change at all.

How to work it

Milestones, not steps.

  1. Baseline, measured. How many barriers per frame, and what does the frame cost? Write both down. Everything is judged against these.
  2. Locate each one. For each barrier, name the exact call that causes it and the system it lives in. You should end up with a short list, and the list is the work plan.
  3. Defer, don’t delete. Each immediate structural change becomes an enqueued one. This step alone should not reduce the barrier count yet — you have moved the work, not consolidated it.
  4. Consolidate playback. This is the actual fix, and it is where the count drops. Deciding where playback belongs is the design decision the drill is testing.
  5. Verify behaviour, frame by frame. Log entity count every frame for 600 frames, before and after, and diff them. An off-by-one-frame difference is a real behavioural change and it will not show up in a final count.
  6. Re-measure. New barrier count, new frame time, and a sentence naming which stall you removed to get it.

When you are done

Answer without checking your code:

  • How many barriers did you start with, how many remain, and what is each remaining one for?
  • For the barrier you kept, what would break if you removed it? If the answer is “nothing,” why is it still there?
  • Did any of your deferred changes land a frame later than before? Which, and did you decide that was acceptable or verify that it made no difference?
  • If the despawn system needed to see entities the spawn system created in the same frame, what would that force, and does your current structure already handle it or would it need another barrier?
  • What is the smallest change to the requirements that would make your solution wrong?

If you conclude that one of the barriers genuinely cannot be removed because a downstream system must observe the change immediately, that is a correct and valuable outcome — provided you can state precisely what observation forces it.

m02.l06