1import * as AWS from "alchemy/AWS";
2import * as Alchemy from "alchemy";
3import * as Cloudflare from "alchemy/Cloudflare";
4import * as Effect from "effect/Effect";
5import * as Layer from "effect/Layer";
6import BunMicrovmLive from "./src/bun-image.ts";
7import ContainerWorker from "./src/container-worker.ts";
8import EffectfulBunLive from "./src/effectful-bun.ts";
9import EffectfulContainerLive from "./src/effectful-container.ts";
10import EffectfulNodeLive from "./src/effectful-node.ts";
11import ExternalMicrovmLive from "./src/external-image.ts";
12import MicrovmWorker from "./src/microvm-worker.ts";
13import NodeMicrovmLive from "./src/node-image.ts";
14import OpencodeMicrovmLive from "./src/opencode-image.ts";
15import Orchestrator from "./src/orchestrator.ts";
16
17/**
18 * MicroVM is a gated AWS Lambda preview. The container benchmark runs against
19 * Cloudflare alone; set `BENCH_MICROVM=1` (on an onboarded account) to also
20 * deploy the two MicroVM images and the Lambda + Worker hosts that boot them.
21 */
22export const benchMicrovm = !!process.env.BENCH_MICROVM;
23
24/**
25 * Combined cold-start benchmark stack.
26 *
27 * - Cloudflare: a {@link ContainerWorker} fronting three container variants
28 * (effectful bundled-Effect image, bun-baseline Dockerfile, remote pre-built
29 * image), each behind its own Durable Object.
30 * - AWS (optional, `BENCH_MICROVM=1`): six MicroVM images (effectful Effect
31 * bundle on bun + node, raw bun + node baselines, an external Python
32 * Dockerfile, and an eagerly-started opencode server) booted by both a
33 * Lambda {@link Orchestrator} and a cross-cloud Cloudflare
34 * {@link MicrovmWorker}.
35 *
36 * Exposes each host's URL so the driver can fire boot/shutdown loads and record
37 * the time-to-usable-service for every variant.
38 */
39export default Alchemy.Stack(
40 "ContainerBenchmark",
41 {
42 providers: Layer.mergeAll(AWS.providers(), Cloudflare.providers()),
43 state: Alchemy.localState(),
44 },
45 Effect.gen(function* () {
46 const containerWorker = yield* ContainerWorker;
47
48 if (!benchMicrovm) {
49 return { containerWorkerUrl: containerWorker.url.as<string>() };
50 }
51
52 const orchestrator = yield* Orchestrator;
53 const microvmWorker = yield* MicrovmWorker;
54 return {
55 containerWorkerUrl: containerWorker.url.as<string>(),
56 lambdaUrl: orchestrator.functionUrl.as<string>(),
57 microvmWorkerUrl: microvmWorker.url.as<string>(),
58 };
59 }).pipe(
60 Effect.provide(
61 benchMicrovm
62 ? Layer.mergeAll(
63 EffectfulContainerLive,
64 EffectfulBunLive,
65 EffectfulNodeLive,
66 BunMicrovmLive,
67 NodeMicrovmLive,
68 ExternalMicrovmLive,
69 OpencodeMicrovmLive,
70 )
71 : EffectfulContainerLive,
72 ),
73 ),
74);