Skip to content

Harden compiled execution contracts - #80

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

Harden compiled execution contracts#80
SandroMaglione merged 1 commit into
mainfrom
codex/machine-refactor-planner-contracts

Conversation

@SandroMaglione

Copy link
Copy Markdown
Member

Summary

  • Give compiled execution plans a runtime-only macrostep and microstep contract instead of claiming to retain generic planner transition diagnostics.
  • Name and document the indexed kernel state as process-owned, and funnel its flat-path mutation through an explicit ownership helper.
  • Freeze shared empty execution arrays and add direct differential witnesses for targetless, reentering, value-only, simultaneous control-changing, and retained-snapshot behavior.

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 quick samples are flat or faster in all machine throughput scenarios; hosted full-size 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.04s
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.25s 0.26s
machine.handle (depth 8) 0.53s 0.53s
machine.handle (depth 12) 0.60s 0.59s
machine.handle (depth 16) 0.65s 0.63s
machine.handle (depth 24) 0.71s 0.73s
machine.handle (wide depth 16) 0.82s 0.79s
machine.handle (parallel/history/choice) 0.67s 0.64s
machine.handle (4 successive calls) 0.59s 0.62s
machine exact input/output/error/services 0.52s 0.53s
execution adapter readiness 0.61s 0.61s

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 7763 64-Core Processor with Node v24.18.0.

Pull request baseline

Scenario Effect Machine XState 5 XState 6 alpha
Plan counter transitions 122,484 transitions/s 132,973 transitions/s 13,130 transitions/s
Drain burst with terminal fence 485,250 increments/s 392,344 increments/s 194,727 increments/s
Drain burst with a change observer 456,413 increments/s 388,628 increments/s 197,060 increments/s
Lookup and send to one child 389,511 increments/s 386,435 increments/s 187,293 increments/s
Start and stop a machine 172,980 machines/s 183,824 machines/s 145,921 machines/s
Start and stop a parent with one child 37,147 families/s 68,129 families/s 41,762 families/s
Plan transitions through a compound state 117,913 transitions/s
Plan transitions through parallel regions 89,556 transitions/s
Drain burst through a compound state 522,138 events/s 344,459 events/s 192,550 events/s
Drain burst through two parallel regions 477,852 events/s 262,420 events/s 145,009 events/s
Drain a compound-state burst with a change observer 476,620 events/s

Effect runtime reference points

Scenario Effect Machine Effect runtime primitives
Start and stop a raw generic process 18,518 processes/s
Start and stop a raw compiled process 68,549 processes/s
Start and interrupt a suspended fiber 166,085 fibers/s
Start and stop a queue worker 115,115 workers/s
Start and stop an actor shell 102,270 actors/s
Start and stop two actor shells 64,855 families/s
Update an owner-only mutable snapshot 316,856,781 updates/s
Update a synchronized snapshot 1,512,781 updates/s
Create, resolve, and await a terminal latch 1,465,244 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 130,677 transitions/s 1.2% MAD 122,484 transitions/s 3.7% MAD -6.3%
Drain burst with terminal fence 519,508 increments/s 3.3% MAD 485,250 increments/s 1.5% MAD -6.6%
Drain burst with a change observer 478,320 increments/s 2.1% MAD 456,413 increments/s 3.0% MAD -4.6%
Lookup and send to one child 405,591 increments/s 1.3% MAD 389,511 increments/s 2.7% MAD -4.0%
Start and stop a machine 168,890 machines/s 0.7% MAD 172,980 machines/s 1.2% MAD +2.4%
Start and stop a parent with one child 32,941 families/s 0.3% MAD 37,147 families/s 5.2% MAD +12.8%
Plan transitions through a compound state 117,840 transitions/s 0.8% MAD 117,913 transitions/s 1.7% MAD +0.1%
Plan transitions through parallel regions 90,905 transitions/s 1.0% MAD 89,556 transitions/s 1.2% MAD -1.5%
Drain burst through a compound state 523,970 events/s 1.5% MAD 522,138 events/s 1.1% MAD -0.3%
Drain burst through two parallel regions 474,438 events/s 1.0% MAD 477,852 events/s 0.3% MAD +0.7%
Drain a compound-state burst with a change observer 475,967 events/s 2.2% MAD 476,620 events/s 1.0% MAD +0.1%
Idle machine heap per unit 1.5 KiB 0.1% MAD 1.5 KiB 0.1% MAD -0.0%
Raw generic managed process heap per unit 12.1 KiB 0.1% MAD 12.1 KiB 0.0% MAD -0.1%
Raw compiled process heap per unit 2.6 KiB 0.0% MAD 2.6 KiB 0.0% MAD +0.0%
Two independent idle machines heap per unit 2.9 KiB 0.0% MAD 2.9 KiB 0.0% 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.0% MAD 5.0 KiB 0.0% MAD -0.0%

Effect runtime reference change from base

Metric Base Base variability PR PR variability Difference
Start and stop a raw generic process 18,546 processes/s 2.2% MAD 18,518 processes/s 0.9% MAD -0.1%
Start and stop a raw compiled process 68,932 processes/s 1.2% MAD 68,549 processes/s 1.1% MAD -0.6%
Start and interrupt a suspended fiber 164,690 fibers/s 0.2% MAD 166,085 fibers/s 1.3% MAD +0.8%
Start and stop a queue worker 115,260 workers/s 0.2% MAD 115,115 workers/s 1.1% MAD -0.1%
Start and stop an actor shell 105,966 actors/s 0.5% MAD 102,270 actors/s 2.2% MAD -3.5%
Start and stop two actor shells 66,059 families/s 0.1% MAD 64,855 families/s 2.6% MAD -1.8%
Update an owner-only mutable snapshot 316,856,781 updates/s 0.0% MAD 316,856,781 updates/s 0.0% MAD 0.0%
Update a synchronized snapshot 1,542,234 updates/s 0.9% MAD 1,512,781 updates/s 2.9% MAD -1.9%
Create, resolve, and await a terminal latch 1,466,162 latches/s 0.2% MAD 1,465,244 latches/s 1.3% MAD -0.1%
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 e830c66 into main Aug 10, 2026
9 checks passed
@SandroMaglione
SandroMaglione deleted the codex/machine-refactor-planner-contracts branch August 10, 2026 11:39
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