1/**
2 * Probe fixture: what does THIS workerd's `node:zlib` offer for a
3 * synchronous, exact-span inflate, and what does each path cost? (See
4 * `src/Git/Protocol/Zlib.ts`.) `?n=<count>` runs each path that many times so
5 * the CLIENT can measure wall time — workerd freezes `performance.now()`
6 * during synchronous work, so the worker cannot time itself.
7 */
8import * as Cloudflare from "@/Cloudflare/index.ts";
9import * as Effect from "effect/Effect";
10import { HttpServerRequest } from "effect/http/HttpServerRequest";
11import * as HttpServerResponse from "effect/http/HttpServerResponse";
12import crypto from "node:crypto";
13import zlib from "node:zlib";
14
15const streamInflate = (z: Uint8Array) =>
16 new Promise<number>((resolve, reject) => {
17 const engine = zlib.createInflate();
18 let out = 0;
19 engine.on("data", (chunk: Uint8Array) => {
20 out += chunk.length;
21 });
22 engine.on("end", () => resolve(out));
23 engine.on("error", reject);
24 engine.end(z);
25 });
26
27export default class ZlibProbeWorker extends Cloudflare.Worker<ZlibProbeWorker>()(
28 "ZlibProbeWorker",
29 { main: import.meta.url },
30 Effect.gen(function* () {
31 return {
32 fetch: Effect.gen(function* () {
33 const request = yield* HttpServerRequest;
34 const url = new URL(request.url, "http://x");
35 const n = Number(url.searchParams.get("n") ?? "0");
36 const which = url.searchParams.get("path") ?? "probe";
37 const content = new TextEncoder().encode("hello ".repeat(500));
38 const z = new Uint8Array(zlib.deflateSync(content));
39 const withTrailer = new Uint8Array(z.length + 7);
40 withTrailer.set(z, 0);
41 withTrailer.set([1, 2, 3, 4, 5, 6, 7], z.length);
42
43 if (which === "probe") {
44 const engine = zlib.createInflate() as unknown as {
45 _processChunk?: unknown;
46 close?: () => void;
47 };
48 const hasProcessChunk = typeof engine._processChunk === "function";
49 engine.close?.();
50 let info: unknown;
51 let infoError: string | undefined;
52 try {
53 const r = zlib.inflateSync(withTrailer, {
54 info: true,
55 } as never) as unknown as {
56 buffer: Uint8Array;
57 engine: { bytesWritten?: number };
58 };
59 info = {
60 outLen: r.buffer?.length,
61 bytesWritten: r.engine?.bytesWritten,
62 expectedConsumed: z.length,
63 };
64 } catch (e) {
65 infoError = String(e);
66 }
67 return HttpServerResponse.jsonUnsafe({
68 hasProcessChunk,
69 info,
70 infoError,
71 contentLen: content.length,
72 });
73 }
74 let ok = 0;
75 let error: string | undefined;
76 try {
77 if (which === "processChunk") {
78 for (let i = 0; i < n; i++) {
79 const engine = zlib.createInflate() as unknown as {
80 _processChunk: (chunk: Uint8Array, flush: number) => Uint8Array;
81 bytesWritten?: number;
82 close?: () => void;
83 };
84 const out = engine._processChunk(
85 withTrailer,
86 zlib.constants.Z_SYNC_FLUSH,
87 );
88 if (
89 out.length === content.length &&
90 engine.bytesWritten === z.length
91 )
92 ok++;
93 engine.close?.();
94 }
95 } else if (which === "processChunkReuse") {
96 // ONE engine for all entries: _processChunk, read the consumed
97 // delta from the cumulative bytesWritten, then reset().
98 const engine = zlib.createInflate() as unknown as {
99 _processChunk: (chunk: Uint8Array, flush: number) => Uint8Array;
100 bytesWritten: number;
101 reset: () => void;
102 close?: () => void;
103 };
104 let consumedBefore = 0;
105 for (let i = 0; i < n; i++) {
106 const out = engine._processChunk(
107 withTrailer,
108 zlib.constants.Z_SYNC_FLUSH,
109 );
110 const consumed = engine.bytesWritten - consumedBefore;
111 consumedBefore = engine.bytesWritten;
112 if (out.length === content.length && consumed === z.length) ok++;
113 engine.reset();
114 }
115 engine.close?.();
116 } else if (which === "info") {
117 for (let i = 0; i < n; i++) {
118 const r = zlib.inflateSync(withTrailer, {
119 info: true,
120 } as never) as unknown as {
121 buffer: Uint8Array;
122 engine: { bytesWritten?: number };
123 };
124 if (
125 r.buffer.length === content.length &&
126 r.engine.bytesWritten === z.length
127 )
128 ok++;
129 }
130 } else if (which === "plain") {
131 for (let i = 0; i < n; i++) {
132 if (zlib.inflateSync(z).length === content.length) ok++;
133 }
134 } else if (which === "sha1") {
135 for (let i = 0; i < n; i++) {
136 const h = crypto.createHash("sha1");
137 h.update(content);
138 if (h.digest().length === 20) ok++;
139 }
140 } else if (which === "deflate6") {
141 const big = new Uint8Array(30 * 1024);
142 for (let i = 0; i < big.length; i++) big[i] = (i * 31) & 0xff;
143 for (let i = 0; i < n; i++) {
144 if (zlib.deflateSync(big, { level: 6 }).length > 0) ok++;
145 }
146 } else if (which === "deflate1") {
147 const big = new Uint8Array(30 * 1024);
148 for (let i = 0; i < big.length; i++) big[i] = (i * 31) & 0xff;
149 for (let i = 0; i < n; i++) {
150 if (zlib.deflateSync(big, { level: 1 }).length > 0) ok++;
151 }
152 } else if (which === "copy") {
153 for (let i = 0; i < n; i++) {
154 if (
155 Uint8Array.from(content.subarray(1)).length ===
156 content.length - 1
157 )
158 ok++;
159 }
160 } else if (which === "jsloop") {
161 // A delta-apply-shaped loop: byte copies with small varint reads.
162 const out = new Uint8Array(content.length);
163 for (let i = 0; i < n; i++) {
164 let at = 0;
165 for (let j = 0; j < content.length; j += 16) {
166 const len = Math.min(16, content.length - j);
167 out.set(content.subarray(j, j + len), at);
168 at += len;
169 }
170 if (at === content.length) ok++;
171 }
172 } else if (which === "effect") {
173 ok = yield* Effect.gen(function* () {
174 let k = 0;
175 for (let i = 0; i < n; i++) {
176 const v = yield* Effect.gen(function* () {
177 let acc = 0;
178 for (let j = 0; j < 20; j++)
179 acc += yield* Effect.sync(() => j);
180 return acc;
181 });
182 if (v === 190) k++;
183 }
184 return k;
185 });
186 } else if (which === "stream") {
187 ok = yield* Effect.promise(async () => {
188 let k = 0;
189 for (let i = 0; i < n; i++)
190 if ((await streamInflate(z)) === content.length) k++;
191 return k;
192 });
193 }
194 } catch (e) {
195 error = String(e);
196 }
197 return HttpServerResponse.jsonUnsafe({ path: which, n, ok, error });
198 }),
199 };
200 }),
201) {}