



























@@ -1,4 +1,4 @@
1-import { spawn, spawnSync, type ChildProcessWithoutNullStreams } from "node:child_process";
1+import { spawn, spawnSync } from "node:child_process";
22import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
33import { request } from "node:http";
44import { createServer } from "node:net";
@@ -7,6 +7,7 @@ import path from "node:path";
77import { performance } from "node:perf_hooks";
88import { pathToFileURL } from "node:url";
99import { parseStrictIntegerOption } from "./lib/dev-tooling-safety.ts";
10+import { delay, stopChild } from "./lib/gateway-bench-child.ts";
10111112type GatewayBenchCase = {
1213config: Record<string, unknown>;
@@ -80,15 +81,6 @@ type BenchmarkFailure = {
8081sampleIndex: number;
8182};
828383-type ChildExit = {
84-exitCode: number | null;
85-signal: string | null;
86-};
87-88-type StopChildResult = ChildExit & {
89-exitedBeforeTeardown: boolean;
90-};
91-9284type PluginFixtureResult = {
9385pluginIds: string[];
9486pluginsDir: string;
@@ -109,8 +101,6 @@ const DEFAULT_RUNS = 5;
109101const DEFAULT_WARMUP = 1;
110102const DEFAULT_TIMEOUT_MS = 30_000;
111103const DEFAULT_ENTRY = "dist/entry.js";
112-const TEARDOWN_GRACE_MS = 2_000;
113-const TEARDOWN_KILL_GRACE_MS = 1_000;
114104115105const BASE_CONFIG = {
116106browser: { enabled: false },
@@ -624,10 +614,6 @@ function requestStatus(port: number, pathname: string): Promise<number> {
624614});
625615}
626616627-function delay(ms: number): Promise<void> {
628-return new Promise((resolve) => setTimeout(resolve, ms));
629-}
630-631617function writePluginFixtures(
632618root: string,
633619count: number,
@@ -710,83 +696,6 @@ function sanitizedEnv(
710696return env;
711697}
712698713-async function stopChild(
714-child: ChildProcessWithoutNullStreams,
715-options: { killGraceMs?: number; teardownGraceMs?: number } = {},
716-): Promise<StopChildResult> {
717-const currentExit = (): ChildExit | null =>
718-child.exitCode != null || child.signalCode != null
719- ? { exitCode: child.exitCode, signal: child.signalCode }
720- : null;
721-722-const existingExit = currentExit();
723-if (existingExit != null) {
724-return { ...existingExit, exitedBeforeTeardown: true };
725-}
726-727-let observedExit: ChildExit | null = null;
728-const exited = new Promise<ChildExit>((resolve) => {
729-child.once("exit", (exitCode, signal) => {
730-observedExit = { exitCode, signal };
731-resolve(observedExit);
732-});
733-});
734-const waitForExit = async (ms: number): Promise<ChildExit | null> =>
735-await Promise.race([exited, delay(ms).then(() => null)]);
736-737-await new Promise<void>((resolve) => setImmediate(resolve));
738-const queuedExit = observedExit ?? currentExit();
739-if (queuedExit != null) {
740-return { ...queuedExit, exitedBeforeTeardown: true };
741-}
742-743-const teardownGraceMs = options.teardownGraceMs ?? TEARDOWN_GRACE_MS;
744-const killGraceMs = options.killGraceMs ?? TEARDOWN_KILL_GRACE_MS;
745-const sentTeardownSignal = killProcessTree(child, "SIGTERM");
746-const gracefulExit = await waitForExit(teardownGraceMs);
747-if (gracefulExit != null) {
748-return { ...gracefulExit, exitedBeforeTeardown: !sentTeardownSignal };
749-}
750-751-const postGraceExit = currentExit() ?? observedExit;
752-if (postGraceExit != null) {
753-return { ...postGraceExit, exitedBeforeTeardown: !sentTeardownSignal };
754-}
755-if (!sentTeardownSignal) {
756-releaseUnsettledChild(child);
757-return { exitCode: null, exitedBeforeTeardown: true, signal: null };
758-}
759-760-killProcessTree(child, "SIGKILL");
761-const killedExit = await waitForExit(killGraceMs);
762-const finalExit = killedExit ?? currentExit() ?? observedExit;
763-if (finalExit != null) {
764-return { ...finalExit, exitedBeforeTeardown: false };
765-}
766-767-releaseUnsettledChild(child);
768-return { exitCode: null, exitedBeforeTeardown: false, signal: "SIGKILL" };
769-}
770-771-function releaseUnsettledChild(child: ChildProcessWithoutNullStreams): void {
772-child.stdin.destroy();
773-child.stdout.destroy();
774-child.stderr.destroy();
775-child.unref();
776-}
777-778-function killProcessTree(child: ChildProcessWithoutNullStreams, signal: NodeJS.Signals): boolean {
779-if (process.platform !== "win32" && child.pid !== undefined) {
780-try {
781-process.kill(-child.pid, signal);
782-return true;
783-} catch {
784-// Fall back to the direct child below.
785-}
786-}
787-return child.kill(signal);
788-}
789-790699function collectStartupTrace(line: string, startupTrace: Record<string, number>): void {
791700const phaseMatch = /startup trace: ([^ ]+) ([0-9.]+)ms total=([0-9.]+)ms(?: (.*))?/u.exec(line);
792701if (phaseMatch) {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。