1- import { Effect , Schema } from "effect"
2- import { Machine } from "../../dist/index.js"
1+ import { readFileSync } from "node:fs"
2+ import { createRequire } from "node:module"
3+ import { dirname , join , resolve } from "node:path"
4+ import { fileURLToPath , pathToFileURL } from "node:url"
5+
6+ const implementationRoot = resolve (
7+ process . env . EFFECT_MACHINE_BENCHMARK_ROOT ?? fileURLToPath ( new URL ( "../.." , import . meta. url ) )
8+ )
9+ const implementationRequire = createRequire ( pathToFileURL ( join ( implementationRoot , "package.json" ) ) )
10+ const effectPackagePath = implementationRequire . resolve ( "effect/package.json" )
11+ const effectPackage = JSON . parse ( readFileSync ( effectPackagePath , "utf8" ) )
12+ const effect = await import ( pathToFileURL ( resolve ( dirname ( effectPackagePath ) , effectPackage . exports [ "." ] ) ) . href )
13+ const { Machine } = await import ( pathToFileURL ( join ( implementationRoot , "dist/index.js" ) ) . href )
14+ const { Effect, Fiber, Option, Schema, Stream } = effect
315
416const CounterState = Schema . TaggedUnion ( {
517 Count : {
@@ -42,6 +54,20 @@ export const counterMachine = Machine.make({
4254 }
4355} )
4456
57+ const ParentState = Schema . TaggedUnion ( { Active : { } } )
58+ const ParentStates = Machine . defineStates ( { Active : ParentState . cases . Active } )
59+ const CounterChild = Machine . child ( "counter" , counterMachine )
60+ const counterParentMachine = Machine . make ( {
61+ id : "RuntimeBenchmarkCounterParent" ,
62+ states : ParentStates . states ,
63+ events : [ ] ,
64+ initial : ( ) => ParentStates . initial . Active ( ParentState . cases . Active . make ( { } ) )
65+ } ) . handle ( {
66+ Active : {
67+ invoke : Machine . invokeMachine ( { child : CounterChild } )
68+ }
69+ } )
70+
4571export const incrementEvent = CounterEvent . cases . Increment . make ( { } )
4672const finishEvent = CounterEvent . cases . Finish . make ( { } )
4773
@@ -67,6 +93,76 @@ export const startCounter = () => Effect.runPromise(Machine.start(counterMachine
6793
6894export const stopCounter = ( ref ) => Effect . runPromise ( ref . stop )
6995
96+ export const startObservedCounter = ( ) =>
97+ Effect . runPromise (
98+ Effect . gen ( function * ( ) {
99+ const ref = yield * Machine . start ( counterMachine )
100+ const observer = yield * ref . changes . pipe ( Stream . runDrain , Effect . forkDetach )
101+ yield * Effect . yieldNow
102+ return { ref, observer }
103+ } )
104+ )
105+
106+ export const stopObservedCounter = ( { ref, observer } ) =>
107+ Effect . runPromise (
108+ ref . stop . pipe ( Effect . ensuring ( Fiber . interrupt ( observer ) ) )
109+ )
110+
111+ export const runObservedCounterBurst = ( { ref, observer } , size ) =>
112+ Effect . runPromise (
113+ Effect . gen ( function * ( ) {
114+ for ( let index = 0 ; index < size ; index += 1 ) {
115+ yield * ref . send ( incrementEvent )
116+ }
117+ yield * ref . send ( finishEvent )
118+ const value = yield * ref . join
119+ yield * Fiber . join ( observer )
120+ return value
121+ } )
122+ )
123+
124+ const waitForCounterChild = ( parent ) =>
125+ Effect . gen ( function * ( ) {
126+ for ( let attempt = 0 ; attempt < 1_000 ; attempt += 1 ) {
127+ const child = yield * parent . child ( CounterChild )
128+ if ( Option . isSome ( child ) ) {
129+ return child . value
130+ }
131+ yield * Effect . yieldNow
132+ }
133+ return yield * Effect . dieMessage ( "Effect Machine child did not become ready" )
134+ } )
135+
136+ export const startChildCounter = ( ) =>
137+ Effect . runPromise (
138+ Effect . gen ( function * ( ) {
139+ const parent = yield * Machine . start ( counterParentMachine )
140+ yield * waitForCounterChild ( parent )
141+ return parent
142+ } )
143+ )
144+
145+ export const stopChildCounter = ( parent ) => Effect . runPromise ( parent . stop )
146+
147+ export const runChildCounterBurst = ( parent , size ) =>
148+ Effect . runPromise (
149+ Effect . gen ( function * ( ) {
150+ for ( let index = 0 ; index < size ; index += 1 ) {
151+ const child = yield * parent . child ( CounterChild )
152+ if ( Option . isNone ( child ) ) {
153+ return yield * Effect . dieMessage ( "Effect Machine child disappeared during the benchmark" )
154+ }
155+ yield * child . value . send ( incrementEvent )
156+ }
157+ const child = yield * parent . child ( CounterChild )
158+ if ( Option . isNone ( child ) ) {
159+ return yield * Effect . dieMessage ( "Effect Machine child disappeared before the terminal fence" )
160+ }
161+ yield * child . value . send ( finishEvent )
162+ return yield * child . value . join
163+ } )
164+ )
165+
70166export const runCounterBurst = ( ref , size ) =>
71167 Effect . runPromise (
72168 Effect . gen ( function * ( ) {
@@ -95,13 +191,31 @@ export const stopCounters = (refs) =>
95191 } )
96192 )
97193
194+ export const startChildCounters = ( count ) =>
195+ Effect . runPromise (
196+ Effect . forEach (
197+ Array . from ( { length : count } ) ,
198+ ( ) =>
199+ Effect . gen ( function * ( ) {
200+ const parent = yield * Machine . start ( counterParentMachine )
201+ yield * waitForCounterChild ( parent )
202+ return parent
203+ } ) ,
204+ { concurrency : 1 }
205+ )
206+ )
207+
208+ export const stopChildCounters = stopCounters
209+
98210export const effectMachineAdapter = {
99211 implementation : "effect-machine" ,
100212 label : "Effect Machine" ,
101213 version : undefined ,
102214 async : true ,
103215 planCounterBatch,
104216 runCounterBurst,
217+ runObservedCounterBurst,
218+ runChildCounterBurst,
105219 runLifecycle : async ( ) => {
106220 const ref = await startCounter ( )
107221 try {
@@ -112,8 +226,24 @@ export const effectMachineAdapter = {
112226 await stopCounter ( ref )
113227 }
114228 } ,
229+ runChildLifecycle : async ( ) => {
230+ const parent = await startChildCounter ( )
231+ try {
232+ if ( ! parent . sessionId . startsWith ( "machine:" ) ) {
233+ throw new Error ( `Child lifecycle benchmark produced invalid session id ${ parent . sessionId } ` )
234+ }
235+ } finally {
236+ await stopChildCounter ( parent )
237+ }
238+ } ,
115239 startCounter,
240+ startObservedCounter,
241+ startChildCounter,
116242 startCounters,
243+ startChildCounters,
117244 stopCounter,
245+ stopChildCounter,
246+ stopChildCounters,
247+ stopObservedCounter,
118248 stopCounters
119249}
0 commit comments