Skip to content

Clarify compiled process lifecycle - #81

Merged
SandroMaglione merged 1 commit into
mainfrom
codex/machine-refactor-runtime-lifecycle
Aug 10, 2026
Merged

Clarify compiled process lifecycle#81
SandroMaglione merged 1 commit into
mainfrom
codex/machine-refactor-runtime-lifecycle

Conversation

@SandroMaglione

Copy link
Copy Markdown
Member

Summary

  • Replace five independent symbol markers with one discriminated process execution descriptor covering child ownership, initialization, and drain context.
  • Model compiled lifecycle (Active, TerminationRequested, Completed) separately from run activity (Initializing, Idle, Draining) while retaining the compact instance layout.
  • Replace manual snapshot flush() choreography with runAfterChanges, add a direct publication-boundary witness, and force the raw compiled benchmark fixture to fail rather than silently fall back.

Changeset

  • Added or updated for a library or package-metadata change
  • Not required because this PR does not change src/ or package.json

Validation

  • pnpm check
  • Relevant example checks, when examples changed (not applicable; no examples changed)
  • Reviewed the automated type-performance report, when the public TypeScript API or inference changed (public API unchanged; local instantiation counts are identical)
  • Reviewed the automated runtime-performance report, when runtime behavior changed (five alternating local samples preserve machine throughput and raw compiled throughput/heap; hosted comparison remains the merge gate)

@github-actions

Copy link
Copy Markdown
Contributor

Type performance

Measured with TypeScript 6.0.3 and skipLibCheck=true.

Scenario Base PR Difference
Effect only 55 55 0 (0.0%)
Import effect-machine 55 55 0 (0.0%)
Machine.defineStates (3 states) 2,965 2,965 0 (0.0%)
Machine.make (3 states, 2 events) 8,715 8,715 0 (0.0%)
machine.handle (3 states, 2 transitions) 23,492 23,492 0 (0.0%)
machine.handle (depth 8) 117,075 117,075 0 (0.0%)
machine.handle (depth 12) 129,713 129,713 0 (0.0%)
machine.handle (depth 16) 145,055 145,055 0 (0.0%)
machine.handle (depth 24) 183,851 183,851 0 (0.0%)
machine.handle (wide depth 16) 214,189 214,189 0 (0.0%)
machine.handle (parallel/history/choice) 132,667 132,667 0 (0.0%)
machine.handle (4 successive calls) 128,674 128,674 0 (0.0%)
machine exact input/output/error/services 110,584 110,584 0 (0.0%)
execution adapter readiness 127,854 127,854 0 (0.0%)

Marginal instantiations are measured against the matching setup without that API call:

Scenario Base PR Difference
Import effect-machine 0 0 0
Machine.defineStates (3 states) 2,910 2,910 0 (0.0%)
Machine.make (3 states, 2 events) 5,742 5,742 0 (0.0%)
machine.handle (3 states, 2 transitions) 14,777 14,777 0 (0.0%)
machine.handle (depth 8) 109,601 109,601 0 (0.0%)
machine.handle (depth 12) 121,039 121,039 0 (0.0%)
machine.handle (depth 16) 135,181 135,181 0 (0.0%)
machine.handle (depth 24) 171,577 171,577 0 (0.0%)
machine.handle (wide depth 16) 202,224 202,224 0 (0.0%)
machine.handle (parallel/history/choice) 114,331 114,331 0 (0.0%)
machine.handle (4 successive calls) 113,703 113,703 0 (0.0%)
machine exact input/output/error/services 100,670 100,670 0 (0.0%)
execution adapter readiness 102,092 102,092 0 (0.0%)
Check times (informational)
Scenario Base PR
Effect only 0.03s 0.03s
Import effect-machine 0.03s 0.03s
Machine.defineStates (3 states) 0.10s 0.11s
Machine.make (3 states, 2 events) 0.16s 0.16s
machine.handle (3 states, 2 transitions) 0.24s 0.25s
machine.handle (depth 8) 0.51s 0.53s
machine.handle (depth 12) 0.56s 0.58s
machine.handle (depth 16) 0.62s 0.61s
machine.handle (depth 24) 0.74s 0.70s
machine.handle (wide depth 16) 0.78s 0.77s
machine.handle (parallel/history/choice) 0.62s 0.63s
machine.handle (4 successive calls) 0.59s 0.61s
machine exact input/output/error/services 0.51s 0.53s
execution adapter readiness 0.58s 0.60s

Type instantiations are the comparison metric. Check time varies with runner load and is informational only.

@github-actions

Copy link
Copy Markdown
Contributor

Runtime performance

Median of 5 independent benchmark processes on AMD EPYC 9V74 80-Core Processor with Node v24.18.0.

Pull request baseline

Scenario Effect Machine XState 5 XState 6 alpha
Plan counter transitions 120,152 transitions/s 136,322 transitions/s 12,155 transitions/s
Drain burst with terminal fence 506,699 increments/s 380,545 increments/s 174,777 increments/s
Drain burst with a change observer 475,241 increments/s 377,455 increments/s 171,828 increments/s
Lookup and send to one child 430,934 increments/s 375,580 increments/s 169,964 increments/s
Start and stop a machine 167,532 machines/s 179,276 machines/s 136,426 machines/s
Start and stop a parent with one child 47,776 families/s 71,577 families/s 45,325 families/s
Plan transitions through a compound state 114,662 transitions/s
Plan transitions through parallel regions 90,789 transitions/s
Drain burst through a compound state 501,900 events/s 334,638 events/s 172,205 events/s
Drain burst through two parallel regions 456,179 events/s 256,702 events/s 137,371 events/s
Drain a compound-state burst with a change observer 461,704 events/s

Effect runtime reference points

Scenario Effect Machine Effect runtime primitives
Start and stop a raw generic process 27,954 processes/s
Start and stop a raw compiled process 71,886 processes/s
Start and interrupt a suspended fiber 156,006 fibers/s
Start and stop a queue worker 115,314 workers/s
Start and stop an actor shell 106,792 actors/s
Start and stop two actor shells 66,658 families/s
Update an owner-only mutable snapshot 312,012,480 updates/s
Update a synchronized snapshot 1,631,436 updates/s
Create, resolve, and await a terminal latch 1,643,383 latches/s
Memory profile Effect Machine XState 5 XState 6 alpha Effect runtime primitives
Idle machine 1.5 KiB 3.8 KiB 2.2 KiB
Raw generic managed process 12.1 KiB
Raw compiled process 2.6 KiB
Two independent idle machines 2.9 KiB 7.3 KiB 3.9 KiB
Idle parent with one child 4.8 KiB 5.5 KiB 4.0 KiB
Parent with observed child registry 9.0 KiB
Parent with observed invoked child snapshots 5.0 KiB
Suspended Effect fiber 0.6 KiB
Effect queue with waiting fiber 2.8 KiB
Effect mailbox actor shell 3.2 KiB
Two Effect actor shells 6.8 KiB

Effect Machine change from base

Metric Base Base variability PR PR variability Difference
Plan counter transitions 119,827 transitions/s 1.2% MAD 120,152 transitions/s 5.2% MAD +0.3%
Drain burst with terminal fence 511,139 increments/s 2.6% MAD 506,699 increments/s 5.5% MAD -0.9%
Drain burst with a change observer 463,153 increments/s 2.5% MAD 475,241 increments/s 3.0% MAD +2.6%
Lookup and send to one child 412,407 increments/s 3.0% MAD 430,934 increments/s 0.6% MAD +4.5%
Start and stop a machine 167,532 machines/s 1.7% MAD 167,532 machines/s 1.2% MAD 0.0%
Start and stop a parent with one child 45,304 families/s 5.4% MAD 47,776 families/s 2.2% MAD +5.5%
Plan transitions through a compound state 114,705 transitions/s 0.3% MAD 114,662 transitions/s 0.3% MAD -0.0%
Plan transitions through parallel regions 90,158 transitions/s 0.6% MAD 90,789 transitions/s 0.5% MAD +0.7%
Drain burst through a compound state 471,178 events/s 6.4% MAD 501,900 events/s 1.9% MAD +6.5%
Drain burst through two parallel regions 426,259 events/s 4.2% MAD 456,179 events/s 1.7% MAD +7.0%
Drain a compound-state burst with a change observer 437,211 events/s 6.1% MAD 461,704 events/s 1.9% MAD +5.6%
Idle machine heap per unit 1.5 KiB 0.1% MAD 1.5 KiB 0.1% MAD +0.2%
Raw generic managed process heap per unit 12.1 KiB 0.0% MAD 12.1 KiB 0.1% MAD +0.1%
Raw compiled process heap per unit 2.6 KiB 0.0% MAD 2.6 KiB 0.5% MAD +0.6%
Two independent idle machines heap per unit 2.9 KiB 0.0% MAD 2.9 KiB 0.1% MAD +0.0%
Idle parent with one child heap per unit 4.8 KiB 0.0% MAD 4.8 KiB 0.0% MAD +0.0%
Parent with observed child registry heap per unit 9.0 KiB 0.0% MAD 9.0 KiB 0.0% MAD +0.0%
Parent with observed invoked child snapshots heap per unit 5.0 KiB 0.1% MAD 5.0 KiB 0.2% MAD +0.2%

Effect runtime reference change from base

Metric Base Base variability PR PR variability Difference
Start and stop a raw generic process 27,522 processes/s 1.2% MAD 27,954 processes/s 2.2% MAD +1.6%
Start and stop a raw compiled process 71,271 processes/s 2.1% MAD 71,886 processes/s 0.6% MAD +0.9%
Start and interrupt a suspended fiber 158,755 fibers/s 1.0% MAD 156,006 fibers/s 0.3% MAD -1.7%
Start and stop a queue worker 116,509 workers/s 0.3% MAD 115,314 workers/s 0.9% MAD -1.0%
Start and stop an actor shell 107,365 actors/s 0.3% MAD 106,792 actors/s 0.5% MAD -0.5%
Start and stop two actor shells 67,604 families/s 0.5% MAD 66,658 families/s 0.9% MAD -1.4%
Update an owner-only mutable snapshot 312,012,480 updates/s 0.0% MAD 312,012,480 updates/s 0.0% MAD 0.0%
Update a synchronized snapshot 1,656,499 updates/s 2.0% MAD 1,631,436 updates/s 2.0% MAD -1.5%
Create, resolve, and await a terminal latch 1,677,509 latches/s 0.7% MAD 1,643,383 latches/s 2.5% MAD -2.0%
Versions and interpretation
  • Effect Machine: 0.3.0
  • XState 5: 5.32.5
  • XState 6 alpha: 6.0.0-alpha.31
  • Effect runtime primitives: 4.0.0-beta.107

Higher throughput is better; lower heap is better. Variability is the median absolute deviation across independent processes, relative to their median. Runtime measurements on shared GitHub-hosted hardware remain informational, so small differences should be confirmed across multiple workflow runs.

@SandroMaglione
SandroMaglione merged commit 2274b8e into main Aug 10, 2026
9 checks passed
@SandroMaglione
SandroMaglione deleted the codex/machine-refactor-runtime-lifecycle branch August 10, 2026 12:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant