From 8e09568bc7eaeceb0cc1fba486585545ac5e37f6 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 22 Mar 2026 11:59:01 -0700 Subject: [PATCH] perf: expand base vitest thread lanes --- scripts/test-find-thread-candidates.mjs | 1 + scripts/test-parallel.mjs | 20 ++- scripts/test-runner-manifest.mjs | 4 + src/config/types.models.ts | 1 + src/tui/components/filterable-select-list.ts | 5 +- src/tui/components/searchable-select-list.ts | 5 +- test/fixtures/test-parallel.behavior.json | 144 ++++++++++++++++++ .../test-find-thread-candidates.test.ts | 13 +- 8 files changed, 183 insertions(+), 10 deletions(-) diff --git a/scripts/test-find-thread-candidates.mjs b/scripts/test-find-thread-candidates.mjs index 1e62ba60464..816a6c6a45b 100644 --- a/scripts/test-find-thread-candidates.mjs +++ b/scripts/test-find-thread-candidates.mjs @@ -80,6 +80,7 @@ export function parseArgs(argv) { export function getExistingThreadCandidateExclusions(behavior) { return new Set([ + ...(behavior.base?.threadSingleton ?? []).map((entry) => entry.file), ...(behavior.unit?.isolated ?? []).map((entry) => entry.file), ...(behavior.unit?.singletonIsolated ?? []).map((entry) => entry.file), ...(behavior.unit?.threadSingleton ?? []).map((entry) => entry.file), diff --git a/scripts/test-parallel.mjs b/scripts/test-parallel.mjs index bc590aeb52c..f8b8dd0bc23 100644 --- a/scripts/test-parallel.mjs +++ b/scripts/test-parallel.mjs @@ -49,6 +49,7 @@ const cleanupTempArtifacts = () => { tempArtifactDir = null; }; const existingUnitConfigFiles = (entries) => existingFiles(entries).filter(isUnitConfigTestFile); +const baseThreadSingletonFiles = existingFiles(behaviorManifest.base?.threadSingleton ?? []); const unitBehaviorIsolatedFiles = existingUnitConfigFiles(behaviorManifest.unit.isolated); const unitSingletonIsolatedFiles = existingUnitConfigFiles(behaviorManifest.unit.singletonIsolated); const unitThreadSingletonFiles = existingUnitConfigFiles(behaviorManifest.unit.threadSingleton); @@ -611,6 +612,7 @@ const resolveFilterMatches = (fileFilter) => { }; const isVmForkSingletonUnitFile = (fileFilter) => unitVmForkSingletonFiles.includes(fileFilter); const isThreadSingletonUnitFile = (fileFilter) => unitThreadSingletonFiles.includes(fileFilter); +const isBaseThreadSingletonFile = (fileFilter) => baseThreadSingletonFiles.includes(fileFilter); const createTargetedEntry = (owner, isolated, filters) => { const name = isolated ? `${owner}-isolated` : owner; const forceForks = isolated; @@ -648,6 +650,12 @@ const createTargetedEntry = (owner, isolated, filters) => { args: ["vitest", "run", "--config", "vitest.unit.config.ts", "--pool=threads", ...filters], }; } + if (owner === "base-threads") { + return { + name, + args: ["vitest", "run", "--config", "vitest.config.ts", "--pool=threads", ...filters], + }; + } if (owner === "extensions") { return { name, @@ -718,7 +726,9 @@ const createPerFileTargetedEntry = (file) => { ? "unit-threads" : isVmForkSingletonUnitFile(file) ? "unit-vmforks" - : target.owner; + : isBaseThreadSingletonFile(file) + ? "base-threads" + : target.owner; return { ...createTargetedEntry(owner, target.isolated, [file]), name: formatPerFileEntryName(owner, file), @@ -747,7 +757,9 @@ const targetedEntries = (() => { ? "unit-threads" : isVmForkSingletonUnitFile(normalizedFile) ? "unit-vmforks" - : target.owner; + : isBaseThreadSingletonFile(normalizedFile) + ? "base-threads" + : target.owner; const key = `${owner}:${target.isolated ? "isolated" : "default"}`; const files = acc.get(key) ?? []; files.push(normalizedFile); @@ -760,7 +772,9 @@ const targetedEntries = (() => { ? "unit-threads" : isVmForkSingletonUnitFile(matchedFile) ? "unit-vmforks" - : target.owner; + : isBaseThreadSingletonFile(matchedFile) + ? "base-threads" + : target.owner; const key = `${owner}:${target.isolated ? "isolated" : "default"}`; const files = acc.get(key) ?? []; files.push(matchedFile); diff --git a/scripts/test-runner-manifest.mjs b/scripts/test-runner-manifest.mjs index fe149839679..f6debde5e62 100644 --- a/scripts/test-runner-manifest.mjs +++ b/scripts/test-runner-manifest.mjs @@ -30,7 +30,11 @@ const normalizeManifestEntries = (entries) => export function loadTestRunnerBehavior() { const raw = tryReadJsonFile(behaviorManifestPath, {}); const unit = raw.unit ?? {}; + const base = raw.base ?? {}; return { + base: { + threadSingleton: normalizeManifestEntries(base.threadSingleton ?? []), + }, unit: { isolated: normalizeManifestEntries(unit.isolated ?? []), singletonIsolated: normalizeManifestEntries(unit.singletonIsolated ?? []), diff --git a/src/config/types.models.ts b/src/config/types.models.ts index e1d60bcf695..9131899b086 100644 --- a/src/config/types.models.ts +++ b/src/config/types.models.ts @@ -29,6 +29,7 @@ type SupportedOpenAICompatFields = Pick< type SupportedThinkingFormat = | NonNullable + | "openrouter" | "qwen-chat-template"; export type ModelCompatConfig = SupportedOpenAICompatFields & { diff --git a/src/tui/components/filterable-select-list.ts b/src/tui/components/filterable-select-list.ts index 19802d8b4df..48cce84fb49 100644 --- a/src/tui/components/filterable-select-list.ts +++ b/src/tui/components/filterable-select-list.ts @@ -1,11 +1,11 @@ import type { Component } from "@mariozechner/pi-tui"; import { Input, + Key, matchesKey, type SelectItem, SelectList, type SelectListTheme, - getKeybindings, } from "@mariozechner/pi-tui"; import chalk from "chalk"; import { fuzzyFilterLower, prepareSearchItems } from "./fuzzy-filter.js"; @@ -110,8 +110,7 @@ export class FilterableSelectList implements Component { } // Escape: clear filter or cancel - const kb = getKeybindings(); - if (kb.matches(keyData, "tui.select.cancel")) { + if (matchesKey(keyData, Key.escape) || matchesKey(keyData, Key.ctrl("c"))) { if (this.filterText) { this.filterText = ""; this.input.setValue(""); diff --git a/src/tui/components/searchable-select-list.ts b/src/tui/components/searchable-select-list.ts index 56526fdbcd8..de8cd911203 100644 --- a/src/tui/components/searchable-select-list.ts +++ b/src/tui/components/searchable-select-list.ts @@ -1,7 +1,7 @@ import { type Component, - getKeybindings, Input, + Key, isKeyRelease, matchesKey, type SelectItem, @@ -362,8 +362,7 @@ export class SearchableSelectList implements Component { return; } - const kb = getKeybindings(); - if (kb.matches(keyData, "tui.select.cancel")) { + if (matchesKey(keyData, Key.escape) || matchesKey(keyData, Key.ctrl("c"))) { if (this.onCancel) { this.onCancel(); } diff --git a/test/fixtures/test-parallel.behavior.json b/test/fixtures/test-parallel.behavior.json index 0dab41d98ae..a62bfb78460 100644 --- a/test/fixtures/test-parallel.behavior.json +++ b/test/fixtures/test-parallel.behavior.json @@ -1,4 +1,140 @@ { + "base": { + "threadSingleton": [ + { + "file": "src/commands/backup.test.ts", + "reason": "Measured ~16% faster under threads than forks on base config after removing process.chdir() from the test." + }, + { + "file": "src/auto-reply/reply/commands-acp/install-hints.test.ts", + "reason": "Measured ~35% faster under threads than forks on base config after removing process.chdir() from the test." + }, + { + "file": "src/agents/pi-extensions/compaction-safeguard.test.ts", + "reason": "Measured ~27% faster under threads than forks on base config after removing process.chdir() from the test." + }, + { + "file": "test/git-hooks-pre-commit.test.ts", + "reason": "Measured ~12% faster under threads than forks on base config while keeping the file green." + }, + { + "file": "test/web-search-provider-boundary.test.ts", + "reason": "Measured ~13% faster under threads than forks on base config while keeping the boundary checks green." + }, + { + "file": "test/scripts/test-runner-manifest.test.ts", + "reason": "Measured ~10% faster under threads than forks on base config while keeping the manifest routing checks green." + }, + { + "file": "test/architecture-smells.test.ts", + "reason": "Measured ~14% faster under threads than forks on base config while keeping the architecture guardrails green." + }, + { + "file": "test/scripts/test-extension.test.ts", + "reason": "Measured ~10% faster under threads than forks on base config while keeping the extension script checks green." + }, + { + "file": "test/vitest-unit-config.test.ts", + "reason": "Measured ~13% faster under threads than forks on base config while keeping the Vitest config checks green." + }, + { + "file": "test/release-check.test.ts", + "reason": "Measured ~11% faster under threads than forks on base config while keeping the release checks green." + }, + { + "file": "src/cli/secrets-cli.test.ts", + "reason": "Measured ~11% faster under threads than forks on base config while keeping secrets CLI coverage green." + }, + { + "file": "src/cli/plugin-registry.test.ts", + "reason": "Measured ~11% faster under threads than forks on base config while keeping plugin registry CLI coverage green." + }, + { + "file": "src/cli/route.test.ts", + "reason": "Measured ~12% faster under threads than forks on base config while keeping route CLI coverage green." + }, + { + "file": "src/cli/exec-approvals-cli.test.ts", + "reason": "Measured ~15% faster under threads than forks on base config while keeping approvals CLI coverage green." + }, + { + "file": "src/cli/browser-cli-manage.timeout-option.test.ts", + "reason": "Measured ~14% faster under threads than forks on base config while keeping browser manage timeout coverage green." + }, + { + "file": "src/cli/browser-cli-manage.test.ts", + "reason": "Measured ~14% faster under threads than forks on base config while keeping browser manage coverage green." + }, + { + "file": "src/cli/deps.test.ts", + "reason": "Measured ~81% faster under threads than forks on base config while keeping dependency checks green." + }, + { + "file": "src/cli/nodes-cli.coverage.test.ts", + "reason": "Measured ~12% faster under threads than forks on base config while keeping nodes CLI coverage green." + }, + { + "file": "src/cli/daemon-cli/restart-health.test.ts", + "reason": "Measured ~35% faster under threads than forks on base config while keeping daemon restart health coverage green." + }, + { + "file": "src/cli/program/config-guard.test.ts", + "reason": "Measured ~14% faster under threads than forks on base config while keeping program config guard coverage green." + }, + { + "file": "src/cli/update-cli/restart-helper.test.ts", + "reason": "Measured ~12% faster under threads than forks on base config while keeping update restart helper coverage green." + }, + { + "file": "src/cli/security-cli.test.ts", + "reason": "Measured ~31% faster under threads than forks on base config while keeping security CLI coverage green." + }, + { + "file": "src/cli/channel-options.test.ts", + "reason": "Measured ~13% faster under threads than forks on base config while keeping channel options coverage green." + }, + { + "file": "src/cli/log-level-option.test.ts", + "reason": "Measured ~11% faster under threads than forks on base config while keeping log level option coverage green." + }, + { + "file": "src/cli/plugin-install-plan.test.ts", + "reason": "Measured ~14% faster under threads than forks on base config while keeping plugin install planning coverage green." + }, + { + "file": "src/cli/memory-cli.test.ts", + "reason": "Measured ~50% faster under threads than forks on base config while keeping memory CLI coverage green." + }, + { + "file": "src/cli/program.nodes-test-helpers.test.ts", + "reason": "Measured ~22% faster under threads than forks on base config while keeping nodes test helper coverage green." + }, + { + "file": "src/cli/skills-cli.test.ts", + "reason": "Measured ~27% faster under threads than forks on base config while keeping skills CLI coverage green." + }, + { + "file": "src/cli/run-main.exit.test.ts", + "reason": "Measured ~12% faster under threads than forks on base config while keeping run-main exit coverage green." + }, + { + "file": "src/cli/completion-fish.test.ts", + "reason": "Measured ~41% faster under threads than forks on base config while keeping fish completion coverage green." + }, + { + "file": "src/cli/config-set-mode.test.ts", + "reason": "Measured ~11% faster under threads than forks on base config while keeping config set mode coverage green." + }, + { + "file": "src/cli/program/build-program.version-alias.test.ts", + "reason": "Measured ~13% faster under threads than forks on base config while keeping version alias coverage green." + }, + { + "file": "src/cli/program/register.agent.test.ts", + "reason": "Measured ~11% faster under threads than forks on base config while keeping register agent coverage green." + } + ] + }, "unit": { "isolated": [ { @@ -377,6 +513,10 @@ "file": "src/plugins/status.test.ts", "reason": "Measured ~10% faster under threads than forks on this host while keeping the file green." }, + { + "file": "src/plugins/bundled-dir.test.ts", + "reason": "Measured ~11% faster under threads than forks on this host while keeping the file green." + }, { "file": "src/plugins/sdk-alias.test.ts", "reason": "Measured ~17% faster under threads than forks on this host after removing process.chdir() from the test." @@ -641,6 +781,10 @@ "file": "src/cli/daemon-cli/install.integration.test.ts", "reason": "Measured ~12% faster under threads than forks on this host while keeping the file green." }, + { + "file": "src/cli/mcp-cli.test.ts", + "reason": "Measured ~12% faster under threads than forks on this host while keeping the file green." + }, { "file": "src/channels/channels-misc.test.ts", "reason": "Measured ~12% faster under threads than forks on this host while keeping the file green." diff --git a/test/scripts/test-find-thread-candidates.test.ts b/test/scripts/test-find-thread-candidates.test.ts index fff07561696..020d9b94e36 100644 --- a/test/scripts/test-find-thread-candidates.test.ts +++ b/test/scripts/test-find-thread-candidates.test.ts @@ -44,6 +44,9 @@ describe("scripts/test-find-thread-candidates exclusions", () => { it("collects already-pinned files across behavior buckets", () => { expect( getExistingThreadCandidateExclusions({ + base: { + threadSingleton: [{ file: "src/base-a.test.ts" }], + }, unit: { isolated: [{ file: "src/a.test.ts" }], singletonIsolated: [{ file: "src/b.test.ts" }], @@ -51,7 +54,15 @@ describe("scripts/test-find-thread-candidates exclusions", () => { vmForkSingleton: [{ file: "src/d.test.ts" }], }, }), - ).toEqual(new Set(["src/a.test.ts", "src/b.test.ts", "src/c.test.ts", "src/d.test.ts"])); + ).toEqual( + new Set([ + "src/base-a.test.ts", + "src/a.test.ts", + "src/b.test.ts", + "src/c.test.ts", + "src/d.test.ts", + ]), + ); }); });