mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-23 14:45:46 +00:00
perf(test): trim runtime lookups and add changed bench
This commit is contained in:
187
scripts/bench-test-changed.mjs
Normal file
187
scripts/bench-test-changed.mjs
Normal file
@@ -0,0 +1,187 @@
|
||||
import { spawnSync } from "node:child_process";
|
||||
import path from "node:path";
|
||||
import { floatFlag, parseFlagArgs, stringFlag } from "./lib/arg-utils.mjs";
|
||||
import { formatMs } from "./lib/vitest-report-cli-utils.mjs";
|
||||
|
||||
function parseArgs(argv) {
|
||||
const args = parseFlagArgs(
|
||||
argv,
|
||||
{
|
||||
cwd: process.cwd(),
|
||||
ref: "origin/main",
|
||||
rss: process.platform === "darwin",
|
||||
mode: "ref",
|
||||
},
|
||||
[
|
||||
stringFlag("--cwd", "cwd"),
|
||||
stringFlag("--ref", "ref"),
|
||||
floatFlag("--max-workers", "maxWorkers", { min: 1 }),
|
||||
],
|
||||
{
|
||||
allowUnknownOptions: true,
|
||||
onUnhandledArg(arg, target) {
|
||||
if (arg === "--no-rss") {
|
||||
target.rss = false;
|
||||
return "handled";
|
||||
}
|
||||
if (arg === "--worktree") {
|
||||
target.mode = "worktree";
|
||||
return "handled";
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
},
|
||||
);
|
||||
return {
|
||||
cwd: path.resolve(args.cwd),
|
||||
mode: args.mode,
|
||||
ref: args.ref,
|
||||
rss: args.rss,
|
||||
...(typeof args.maxWorkers === "number" ? { maxWorkers: Math.trunc(args.maxWorkers) } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
function quoteArg(arg) {
|
||||
return /[^A-Za-z0-9_./:-]/.test(arg) ? JSON.stringify(arg) : arg;
|
||||
}
|
||||
|
||||
function runGitList(args, cwd) {
|
||||
const result = spawnSync("git", args, {
|
||||
cwd,
|
||||
encoding: "utf8",
|
||||
});
|
||||
if (result.status !== 0) {
|
||||
throw new Error(result.stderr || result.stdout || `git ${args.join(" ")} failed`);
|
||||
}
|
||||
return result.stdout
|
||||
.split("\n")
|
||||
.map((line) => line.trim())
|
||||
.filter((line) => line.length > 0);
|
||||
}
|
||||
|
||||
function listChangedPaths(opts) {
|
||||
if (opts.mode === "worktree") {
|
||||
return [
|
||||
...new Set([
|
||||
...runGitList(["diff", "--name-only", "--relative", "HEAD", "--"], opts.cwd),
|
||||
...runGitList(["ls-files", "--others", "--exclude-standard"], opts.cwd),
|
||||
]),
|
||||
].toSorted((left, right) => left.localeCompare(right));
|
||||
}
|
||||
return runGitList(["diff", "--name-only", `${opts.ref}...HEAD`], opts.cwd);
|
||||
}
|
||||
|
||||
function parseMaxRssKb(output) {
|
||||
const match = output.match(/(\d+)\s+maximum resident set size/u);
|
||||
return match ? Number.parseInt(match[1], 10) : null;
|
||||
}
|
||||
|
||||
function formatRss(valueKb) {
|
||||
if (valueKb === null) {
|
||||
return "n/a";
|
||||
}
|
||||
return `${(valueKb / 1024).toFixed(1)}MB`;
|
||||
}
|
||||
|
||||
function runBenchCommand(params) {
|
||||
const env = { ...process.env };
|
||||
if (typeof params.maxWorkers === "number") {
|
||||
env.OPENCLAW_VITEST_MAX_WORKERS = String(params.maxWorkers);
|
||||
}
|
||||
const startedAt = process.hrtime.bigint();
|
||||
const commandArgs = params.rss ? ["-l", ...params.command] : params.command;
|
||||
const result = spawnSync(
|
||||
params.rss ? "/usr/bin/time" : commandArgs[0],
|
||||
params.rss ? commandArgs : commandArgs.slice(1),
|
||||
{
|
||||
cwd: params.cwd,
|
||||
env,
|
||||
encoding: "utf8",
|
||||
maxBuffer: 1024 * 1024 * 32,
|
||||
},
|
||||
);
|
||||
const elapsedMs = Number(process.hrtime.bigint() - startedAt) / 1_000_000;
|
||||
const output = `${result.stdout ?? ""}${result.stderr ?? ""}`;
|
||||
return {
|
||||
elapsedMs,
|
||||
maxRssKb: params.rss ? parseMaxRssKb(output) : null,
|
||||
status: result.status ?? 1,
|
||||
output,
|
||||
};
|
||||
}
|
||||
|
||||
function printRunSummary(label, result) {
|
||||
console.log(
|
||||
`${label.padEnd(8, " ")} wall=${formatMs(result.elapsedMs).padStart(9, " ")} rss=${formatRss(
|
||||
result.maxRssKb,
|
||||
).padStart(9, " ")}`,
|
||||
);
|
||||
}
|
||||
|
||||
const opts = parseArgs(process.argv.slice(2));
|
||||
const changedPaths = listChangedPaths(opts);
|
||||
if (changedPaths.length === 0) {
|
||||
console.log(
|
||||
opts.mode === "worktree"
|
||||
? "[bench-test-changed] no changed paths in worktree"
|
||||
: `[bench-test-changed] no changed paths for ${opts.ref}...HEAD`,
|
||||
);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
console.log(
|
||||
opts.mode === "worktree"
|
||||
? "[bench-test-changed] mode=worktree"
|
||||
: `[bench-test-changed] ref=${opts.ref}`,
|
||||
);
|
||||
console.log("[bench-test-changed] changed paths:");
|
||||
for (const changedPath of changedPaths) {
|
||||
console.log(`- ${changedPath}`);
|
||||
}
|
||||
|
||||
const routedCommand =
|
||||
opts.mode === "worktree"
|
||||
? [process.execPath, "scripts/test-projects.mjs", ...changedPaths]
|
||||
: [process.execPath, "scripts/test-projects.mjs", "--changed", opts.ref];
|
||||
const rootCommand = [
|
||||
process.execPath,
|
||||
"scripts/run-vitest.mjs",
|
||||
"run",
|
||||
"--config",
|
||||
"vitest.config.ts",
|
||||
...changedPaths,
|
||||
];
|
||||
|
||||
console.log(`[bench-test-changed] routed: ${routedCommand.map(quoteArg).join(" ")}`);
|
||||
const routed = runBenchCommand({
|
||||
command: routedCommand,
|
||||
cwd: opts.cwd,
|
||||
rss: opts.rss,
|
||||
...(typeof opts.maxWorkers === "number" ? { maxWorkers: opts.maxWorkers } : {}),
|
||||
});
|
||||
if (routed.status !== 0) {
|
||||
process.stderr.write(routed.output);
|
||||
process.exit(routed.status);
|
||||
}
|
||||
|
||||
console.log(`[bench-test-changed] root: ${rootCommand.map(quoteArg).join(" ")}`);
|
||||
const root = runBenchCommand({
|
||||
command: rootCommand,
|
||||
cwd: opts.cwd,
|
||||
rss: opts.rss,
|
||||
...(typeof opts.maxWorkers === "number" ? { maxWorkers: opts.maxWorkers } : {}),
|
||||
});
|
||||
if (root.status !== 0) {
|
||||
process.stderr.write(root.output);
|
||||
process.exit(root.status);
|
||||
}
|
||||
|
||||
printRunSummary("routed", routed);
|
||||
printRunSummary("root", root);
|
||||
console.log(
|
||||
`[bench-test-changed] delta wall=${formatMs(root.elapsedMs - routed.elapsedMs)} rss=${
|
||||
routed.maxRssKb !== null && root.maxRssKb !== null
|
||||
? formatRss(root.maxRssKb - routed.maxRssKb)
|
||||
: "n/a"
|
||||
}`,
|
||||
);
|
||||
Reference in New Issue
Block a user