From 14329d1b982c926111f15eb0afcd9a14b8a3a779 Mon Sep 17 00:00:00 2001 From: "paseo-bot[bot]" <266920839+paseo-bot[bot]@users.noreply.github.com> Date: Fri, 30 Oct 2026 12:08:00 +0000 Subject: [PATCH] test(server): diagnose recurring config responsiveness failure --- .../src/utils/paseo-config-file.test.ts | 35 ++++++++++--------- .../test-fixtures/config-responsiveness.ts | 23 ++++++++++++ 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/packages/server/src/utils/paseo-config-file.test.ts b/packages/server/src/utils/paseo-config-file.test.ts index 6a7e43c757..ae58676e8a 100644 --- a/packages/server/src/utils/paseo-config-file.test.ts +++ b/packages/server/src/utils/paseo-config-file.test.ts @@ -133,22 +133,25 @@ describe("paseo config file substrate", () => { expect(blockingMs).toBeLessThan(20); }); - it("keeps main-thread work below 20ms while admitting large configs", async () => { - const config = { - scripts: Object.fromEntries( - Array.from({ length: 7_000 }, (_, i) => [`script${i}`, { command: "echo hi" }]), - ), - worktree: { setup: "npm ci" }, - }; - await writeFile(join(tempDir, "paseo.json"), JSON.stringify(config)); - const { result, blockingMs, filesystemRequests, yields, workerMessages } = - await measureConfigRead(tempDir); - expect(result).toEqual({ ok: true, config, revision: await statPaseoConfigPath(tempDir) }); - expect(blockingMs).toBeLessThan(20); - expect(filesystemRequests).toBeGreaterThan(0); - expect(yields).toBeGreaterThan(0); - expect(workerMessages).toBe(0); - }); + it.each(Array.from({ length: 30 }, (_, i) => i))( + "keeps main-thread work below 20ms while admitting large configs (%i)", + async () => { + const config = { + scripts: Object.fromEntries( + Array.from({ length: 7_000 }, (_, i) => [`script${i}`, { command: "echo hi" }]), + ), + worktree: { setup: "npm ci" }, + }; + await writeFile(join(tempDir, "paseo.json"), JSON.stringify(config)); + const { result, blockingMs, filesystemRequests, yields, workerMessages } = + await measureConfigRead(tempDir); + expect(result).toEqual({ ok: true, config, revision: await statPaseoConfigPath(tempDir) }); + expect(blockingMs).toBeLessThan(20); + expect(filesystemRequests).toBeGreaterThan(0); + expect(yields).toBeGreaterThan(0); + expect(workerMessages).toBe(0); + }, + ); it("rejects a 32MiB config with main-thread work below 20ms", async () => { await writeFile( diff --git a/packages/server/src/utils/test-fixtures/config-responsiveness.ts b/packages/server/src/utils/test-fixtures/config-responsiveness.ts index 9e151c805a..8a7a731c8b 100644 --- a/packages/server/src/utils/test-fixtures/config-responsiveness.ts +++ b/packages/server/src/utils/test-fixtures/config-responsiveness.ts @@ -1,4 +1,5 @@ import { createHook, executionAsyncResource } from "node:async_hooks"; +import { Session } from "node:inspector/promises"; import { MessagePort } from "node:worker_threads"; import assert from "node:assert/strict"; import { setImmediate as nextTurn } from "node:timers/promises"; @@ -17,8 +18,30 @@ const activity = createHook({ if (executionAsyncResource() instanceof MessagePort) workerMessages++; }, }).enable(); +const profiler = new Session(); +profiler.connect(); +await profiler.post("Profiler.enable"); +await profiler.post("Profiler.setSamplingInterval", { interval: 100 }); +await profiler.post("Profiler.start"); const measured = await measureMainThreadWork("project config main-thread work", () => readPaseoConfigForEdit(directory), ); activity.disable(); +const { profile } = await profiler.post("Profiler.stop"); +profiler.disconnect(); +if (measured.blockingMs >= 20) { + const nodes = new Map(profile.nodes.map((node) => [node.id, node])); + const samples = new Map(); + for (const [index, id] of (profile.samples ?? []).entries()) { + samples.set(id, (samples.get(id) ?? 0) + (profile.timeDeltas?.[index] ?? 0)); + } + const hottest = [...samples] + .sort((a, b) => b[1] - a[1]) + .slice(0, 20) + .map(([id, micros]) => { + const frame = nodes.get(id)!.callFrame; + return { function: frame.functionName, line: frame.lineNumber, milliseconds: micros / 1000 }; + }); + process.stderr.write(`Config CPU diagnostic: ${JSON.stringify(hottest)}\n`); +} process.stdout.write(JSON.stringify({ ...measured, workerMessages }));