Luigit
repositories / pi-ext

pi-ext

bugabingas pi extensions

owned by admin

scripts/codegen/pi-ext-debug.bench.mjs

Raw
// Benchmark the generated debug writer the way Pi startup exercises it:
// one fresh module copy per extension, enabled through user settings, logging
// against already-existing private directories. Prints Go benchmark lines.
// Usage: node pi-ext-debug.bench.mjs [template.ts]
import { spawnSync } from "node:child_process";
import {
	mkdirSync,
	mkdtempSync,
	readFileSync,
	rmSync,
	writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath, pathToFileURL } from "node:url";

const EXTENSIONS = 40;
const ROUNDS = Number(process.env.PI_EXT_DEBUG_BENCH_ROUNDS ?? 30);
const WARM_RECORDS = 2_000;
const here = dirname(fileURLToPath(import.meta.url));

if (process.argv[2] === "--child") {
	const [, , , moduleDir] = process.argv;
	const started = process.hrtime.bigint();
	const loaded = [];
	for (let index = 0; index < EXTENSIONS; index++) {
		const module = await import(
			pathToFileURL(join(moduleDir, `ext-${index}.ts`)).href
		);
		const debug = module.defineDebug({
			events: ["session.start", "session.shutdown"],
			spans: ["catalog.refresh"],
			fields: { count: "number", network: "boolean", outcome: ["ok"] },
		});
		debug.dbg?.("session.start", { count: index });
		for (let refresh = 0; refresh < 2; refresh++)
			debug.span?.("catalog.refresh", { network: false })("finish", {
				outcome: "ok",
			});
		loaded.push(debug);
	}
	const startup = process.hrtime.bigint() - started;
	const [first] = loaded;
	const warmStarted = process.hrtime.bigint();
	for (let index = 0; index < WARM_RECORDS; index++)
		first.dbg?.("session.start", { count: index });
	const warm = (process.hrtime.bigint() - warmStarted) / BigInt(WARM_RECORDS);
	for (const debug of loaded) debug.closeDebug();
	console.log(`${startup} ${warm}`);
	process.exit(0);
}

const template = resolve(
	process.argv[2] ?? join(here, "templates", "pi-ext-debug.ts"),
);
const root = mkdtempSync(join(tmpdir(), "pi-ext-debug-bench-"));
try {
	const moduleDir = join(root, "modules");
	mkdirSync(moduleDir);
	const source = readFileSync(template, "utf8");
	for (let index = 0; index < EXTENSIONS; index++)
		writeFileSync(
			join(moduleDir, `ext-${index}.ts`),
			source.replaceAll("{{extension-slug}}", `bench-${index}`),
		);
	const agentDir = join(root, "agent");
	mkdirSync(agentDir);
	// Realistic user settings size (~4.5 KB) with global debug selection.
	writeFileSync(
		join(agentDir, "settings.json"),
		JSON.stringify({
			"pi-ext": { debug: true },
			padding: Array.from({ length: 60 }, (_, index) => ({
				key: `setting-${index}`,
				value: "x".repeat(48),
			})),
		}),
	);
	const env = {
		...process.env,
		HOME: join(root, "home"),
		XDG_STATE_HOME: join(root, "state"),
		PI_CODING_AGENT_DIR: agentDir,
	};
	const run = () => {
		const result = spawnSync(
			process.execPath,
			[
				"--no-warnings",
				"--experimental-strip-types",
				fileURLToPath(import.meta.url),
				"--child",
				moduleDir,
			],
			{ env, encoding: "utf8" },
		);
		if (result.status !== 0) throw new Error(result.stderr);
		return result.stdout.trim().split(" ");
	};
	// First run creates the directories; later runs match normal startups.
	for (let index = 0; index < 3; index++) run();
	console.log(`goos: ${process.platform}`);
	console.log(`goarch: ${process.arch}`);
	console.log("pkg: pi-ext/debug");
	for (let round = 0; round < ROUNDS; round++) {
		const [startup, warm] = run();
		console.log(`BenchmarkDebugStartup${EXTENSIONS}\t1\t${startup} ns/op`);
		console.log(`BenchmarkDebugRecordWarm\t${WARM_RECORDS}\t${warm} ns/op`);
	}
} finally {
	rmSync(root, { recursive: true, force: true });
}