statelyai / xstate

Actor-based state management & orchestration for complex app logic.
https://stately.ai/docs
MIT License
27.21k stars 1.26k forks source link

resolveStop is slow for large systems with unpredictable/random ids #4990

Open ivankoleda opened 4 months ago

ivankoleda commented 4 months ago

XState version

XState version 5

Description

Stopping a system with lots of children with non-sequential/unpredicatable ids is slow.

Consider a following system

Starting and stopping such a systems takes way more time than a system with predictable ids like 0, 1, 2...

It probably comes down to this line. https://github.com/statelyai/xstate/blob/cbec1a50a67f64402f811e4ec912795762b5adb9/packages/core/src/actions/stopChild.ts#L45 My guess having unpredictable object keys forces V8 to use less efficient internal structures for object representation. Maybe using a Map internally can solve an issue. Although, exposing it externally would be a breaking change.

Expected result

If we provide predictable id in spawnChild, starting and stopping the system is fast.

for (let i = 0; i < 1_000; i++) {
  enqueue.spawnChild('child', {
    id: String(i),
  });
}

https://github.com/user-attachments/assets/9153faa8-d622-4601-a70e-dc12bbb4a1a7

Screenshot 2024-07-18 at 22 10 50

Actual result

If we provide a random id, starting and stopping the system takes about 1 second on M3 mac without CPU slowdown.

for (let i = 0; i < 1_000; i++) {
  enqueue.spawnChild('child', {
    id: self.crypto.randomUUID(),
  });
}

https://github.com/user-attachments/assets/eb07c9b2-77f6-408f-b93e-031de4f58a36

Screenshot 2024-07-18 at 21 38 14

Reproduction

https://stackblitz.com/edit/vitejs-vite-y3j896?file=src%2FApp.jsx

Additional context

No response