

















@@ -2,6 +2,7 @@ import { spawn } from "node:child_process";
22import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
33import os from "node:os";
44import path from "node:path";
5+import { pathToFileURL } from "node:url";
5667type CommandCase = {
78id: string;
@@ -394,6 +395,17 @@ function parseRepeatableFlag(flag: string): string[] {
394395}
395396396397function parsePositiveInt(raw: string | undefined, fallback: number): number {
398+if (!raw) {
399+return fallback;
400+}
401+const parsed = Number.parseInt(raw, 10);
402+if (!Number.isFinite(parsed) || parsed < 1) {
403+return fallback;
404+}
405+return parsed;
406+}
407+408+function parseNonNegativeInt(raw: string | undefined, fallback: number): number {
397409if (!raw) {
398410return fallback;
399411}
@@ -747,6 +759,25 @@ function printDelta(primary: SuiteResult, secondary: SuiteResult): void {
747759}
748760}
749761762+export function collectFailedSamples(result: SuiteResult): string[] {
763+const failures: string[] = [];
764+for (const commandCase of result.cases) {
765+if (commandCase.samples.length === 0) {
766+failures.push(`${result.entry} ${commandCase.id}: no measured samples`);
767+continue;
768+}
769+for (const [sampleIndex, sample] of commandCase.samples.entries()) {
770+const label = `${result.entry} ${commandCase.id} sample ${sampleIndex + 1}`;
771+if (sample.signal !== null) {
772+failures.push(`${label}: exited via signal ${sample.signal}`);
773+} else if (sample.exitCode !== 0) {
774+failures.push(`${label}: exited with code ${String(sample.exitCode)}`);
775+}
776+}
777+}
778+return failures;
779+}
780+750781async function buildSuiteResult(params: {
751782entry: string;
752783options: CliOptions;
@@ -796,7 +827,7 @@ function parseOptions(): CliOptions {
796827entryPrimary: parseFlagValue("--entry-primary") ?? parseFlagValue("--entry") ?? DEFAULT_ENTRY,
797828entrySecondary: parseFlagValue("--entry-secondary"),
798829runs: parsePositiveInt(parseFlagValue("--runs"), DEFAULT_RUNS),
799-warmup: parsePositiveInt(parseFlagValue("--warmup"), DEFAULT_WARMUP),
830+warmup: parseNonNegativeInt(parseFlagValue("--warmup"), DEFAULT_WARMUP),
800831timeoutMs: parsePositiveInt(parseFlagValue("--timeout-ms"), DEFAULT_TIMEOUT_MS),
801832json: hasFlag("--json"),
802833output: parseFlagValue("--output"),
@@ -864,6 +895,10 @@ async function main(): Promise<void> {
864895 primary,
865896secondary: secondary ?? null,
866897};
898+const failures = [
899+ ...collectFailedSamples(primary),
900+ ...(secondary ? collectFailedSamples(secondary) : []),
901+];
867902868903if (options.output) {
869904mkdirSync(path.dirname(options.output), { recursive: true });
@@ -872,6 +907,12 @@ async function main(): Promise<void> {
872907873908if (options.json) {
874909console.log(JSON.stringify(report, null, 2));
910+if (failures.length > 0) {
911+process.exitCode = 1;
912+for (const failure of failures) {
913+console.error(`[startup-bench] ${failure}`);
914+}
915+}
875916return;
876917}
877918@@ -894,9 +935,28 @@ async function main(): Promise<void> {
894935printSuite(secondary);
895936printDelta(primary, secondary);
896937}
938+939+if (failures.length > 0) {
940+process.exitCode = 1;
941+console.error("\nFailed startup benchmark samples:");
942+for (const failure of failures) {
943+console.error(`- ${failure}`);
944+}
945+}
897946} finally {
898947rmSync(tmpDir, { recursive: true, force: true });
899948}
900949}
901950902-await main();
951+export const testing = {
952+ collectFailedSamples,
953+ parseNonNegativeInt,
954+ parsePositiveInt,
955+};
956+957+if (import.meta.url === pathToFileURL(process.argv[1] ?? "").href) {
958+await main().catch((error: unknown) => {
959+console.error(error instanceof Error ? error.stack : String(error));
960+process.exit(1);
961+});
962+}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。