perf: default unit vitest lanes to threads

This commit is contained in:
Peter Steinberger
2026-03-22 12:24:47 -07:00
parent e64dbb00b3
commit e39d5b9ef8
2 changed files with 236 additions and 220 deletions

View File

@@ -85,14 +85,13 @@ const testProfile =
const isMacMiniProfile = testProfile === "macmini";
// Vitest executes Node tests through Vite's SSR/module-runner pipeline, so the
// shared unit lane still retains transformed ESM/module state even when the
// tests themselves are not "server rendering" a website. vmForks can win in
// ideal transform-heavy cases, but for this repo we measured higher aggregate
// CPU load and fatal heap OOMs on memory-constrained dev machines and CI when
// unit-fast stayed on vmForks. Keep forks as the default unless that evidence
// is re-run and replaced:
// PR: https://github.com/openclaw/openclaw/pull/51145
// OOM evidence: https://github.com/openclaw/openclaw/pull/51145#issuecomment-4099663958
// Preserve OPENCLAW_TEST_VM_FORKS=1 as the explicit override/debug escape hatch.
// tests themselves are not "server rendering" a website. We previously kept
// forks as the default after vmFork OOM regressions on constrained hosts. On
// 2026-03-22, a direct full-unit threads run finished 1109/1110 green; the sole
// correctness exception stayed on the manifest fork lane, so the wrapper now
// defaults unit runs to threads while preserving explicit fork/vmFork escapes.
// Preserve OPENCLAW_TEST_UNIT_DEFAULT_POOL=forks or OPENCLAW_TEST_VM_FORKS=1 as
// explicit debug escape hatches.
const supportsVmForks = Number.isFinite(nodeMajor) ? nodeMajor <= 24 : true;
const useVmForks = process.env.OPENCLAW_TEST_VM_FORKS === "1" && supportsVmForks;
const forceIsolation =
@@ -103,6 +102,15 @@ const disableIsolation =
process.env.OPENCLAW_TEST_NO_ISOLATE !== "false";
const includeGatewaySuite = process.env.OPENCLAW_TEST_INCLUDE_GATEWAY === "1";
const includeExtensionsSuite = process.env.OPENCLAW_TEST_INCLUDE_EXTENSIONS === "1";
const parsePoolOverride = (value, fallback) => {
if (value === "threads" || value === "forks") {
return value;
}
if (value === "vmForks") {
return supportsVmForks ? value : "forks";
}
return fallback;
};
// Even on low-memory hosts, keep the isolated lane split so files like
// git-commit.test.ts still get the worker/process isolation they require.
const shouldSplitUnitRuns = testProfile !== "serial";
@@ -263,8 +271,16 @@ const allKnownTestFiles = [
...walkTestFiles(path.join("ui", "src", "ui")),
]),
];
const defaultUnitPool = parsePoolOverride(process.env.OPENCLAW_TEST_UNIT_DEFAULT_POOL, "threads");
const isTargetedIsolatedUnitFile = (fileFilter) =>
unitBehaviorIsolatedFiles.includes(fileFilter) ||
unitSingletonBatchFiles.includes(fileFilter) ||
unitMemorySingletonFiles.includes(fileFilter);
const inferTarget = (fileFilter) => {
const isolated = unitBehaviorIsolatedFiles.includes(fileFilter);
const isolated = isTargetedIsolatedUnitFile(fileFilter);
if (isUnitConfigTestFile(fileFilter)) {
return { owner: "unit", isolated };
}
if (fileFilter.endsWith(".live.test.ts")) {
return { owner: "live", isolated };
}
@@ -465,7 +481,7 @@ const unitFastEntries = unitFastBuckets.flatMap((files, index) => {
"run",
"--config",
"vitest.unit.config.ts",
`--pool=${useVmForks ? "vmForks" : "forks"}`,
`--pool=${defaultUnitPool}`,
...(disableIsolation ? ["--isolate=false"] : []),
],
}));
@@ -638,7 +654,7 @@ const createTargetedEntry = (owner, isolated, filters) => {
"run",
"--config",
"vitest.unit.config.ts",
`--pool=${forceForks ? "forks" : useVmForks ? "vmForks" : "forks"}`,
`--pool=${forceForks ? "forks" : defaultUnitPool}`,
...(disableIsolation ? ["--isolate=false"] : []),
...filters,
],

View File

@@ -12,214 +12,6 @@
{
"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."
},
{
"file": "test/scripts/test-parallel.test.ts",
"reason": "Measured ~44% faster under threads than forks on base config while keeping the parallel wrapper checks green."
},
{
"file": "test/scripts/test-find-thread-candidates.test.ts",
"reason": "Measured ~19% faster under threads than forks on base config while keeping the thread candidate helper checks green."
},
{
"file": "test/openclaw-npm-release-check.test.ts",
"reason": "Measured ~19% faster under threads than forks on base config while keeping the npm release checks green."
},
{
"file": "src/cli/pairing-cli.test.ts",
"reason": "Measured ~12% faster under threads than forks on base config while keeping pairing CLI coverage green."
},
{
"file": "src/cli/daemon-cli.coverage.test.ts",
"reason": "Measured ~11% faster under threads than forks on base config while keeping daemon CLI coverage green."
},
{
"file": "src/cli/config-set-input.test.ts",
"reason": "Measured ~43% faster under threads than forks on base config while keeping config set input coverage green."
},
{
"file": "src/cli/cron-cli.test.ts",
"reason": "Measured ~18% faster under threads than forks on base config while keeping cron CLI coverage green."
},
{
"file": "src/cli/plugins-config.test.ts",
"reason": "Measured ~15% faster under threads than forks on base config while keeping plugin config coverage green."
},
{
"file": "src/cli/program/register.configure.test.ts",
"reason": "Measured ~12% faster under threads than forks on base config while keeping register configure coverage green."
},
{
"file": "src/cli/program/command-tree.test.ts",
"reason": "Measured ~10% faster under threads than forks on base config while keeping command tree coverage green."
},
{
"file": "src/cli/program/register.subclis.test.ts",
"reason": "Measured ~11% faster under threads than forks on base config while keeping sub-CLI registration coverage green."
},
{
"file": "test/vitest-unit-paths.test.ts",
"reason": "Measured ~11% faster under threads than forks on base config while keeping unit path checks green."
},
{
"file": "test/scripts/check-channel-agnostic-boundaries.test.ts",
"reason": "Measured ~29% faster under threads than forks on base config while keeping channel-agnostic boundary checks green."
},
{
"file": "test/plugin-npm-release.test.ts",
"reason": "Measured ~10% faster under threads than forks on base config while keeping npm release checks green."
},
{
"file": "src/cli/daemon-cli-compat.test.ts",
"reason": "Measured ~12% faster under threads than forks on base config while keeping daemon CLI compatibility coverage green."
},
{
"file": "src/cli/program/command-registry.test.ts",
"reason": "Measured ~10% faster under threads than forks on base config while keeping command registry coverage green."
},
{
"file": "src/cli/program.force.test.ts",
"reason": "Measured ~14% faster under threads than forks on base config while keeping force option coverage green."
},
{
"file": "src/cli/cli-utils.test.ts",
"reason": "Measured ~15% faster under threads than forks on base config while keeping CLI utility coverage green."
},
{
"file": "src/cli/devices-cli.test.ts",
"reason": "Measured ~21% faster under threads than forks on base config while keeping devices CLI coverage green."
},
{
"file": "src/cli/message-secret-scope.test.ts",
"reason": "Measured ~16% faster under threads than forks on base config while keeping message secret scope coverage green."
},
{
"file": "src/cli/banner.test.ts",
"reason": "Measured ~30% faster under threads than forks on base config while keeping banner rendering coverage green."
},
{
"file": "src/cli/gateway-cli.coverage.test.ts",
"reason": "Measured ~18% faster under threads than forks on base config while keeping gateway CLI coverage green."
}
]
},
@@ -257,7 +49,7 @@
},
{
"file": "src/secrets/runtime.integration.test.ts",
"reason": "Secrets runtime activation/write-through integration coverage is CPU-heavy and safer outside the shared unit-fast lane."
"reason": "Secrets runtime activation/write-through integration coverage fails under a direct full-unit threads run and is safer on the fork singleton lane."
},
{
"file": "src/memory/index.test.ts",
@@ -529,6 +321,214 @@
}
],
"threadSingleton": [
{
"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."
},
{
"file": "test/scripts/test-parallel.test.ts",
"reason": "Measured ~44% faster under threads than forks on base config while keeping the parallel wrapper checks green."
},
{
"file": "test/scripts/test-find-thread-candidates.test.ts",
"reason": "Measured ~19% faster under threads than forks on base config while keeping the thread candidate helper checks green."
},
{
"file": "test/openclaw-npm-release-check.test.ts",
"reason": "Measured ~19% faster under threads than forks on base config while keeping the npm release checks green."
},
{
"file": "src/cli/pairing-cli.test.ts",
"reason": "Measured ~12% faster under threads than forks on base config while keeping pairing CLI coverage green."
},
{
"file": "src/cli/daemon-cli.coverage.test.ts",
"reason": "Measured ~11% faster under threads than forks on base config while keeping daemon CLI coverage green."
},
{
"file": "src/cli/config-set-input.test.ts",
"reason": "Measured ~43% faster under threads than forks on base config while keeping config set input coverage green."
},
{
"file": "src/cli/cron-cli.test.ts",
"reason": "Measured ~18% faster under threads than forks on base config while keeping cron CLI coverage green."
},
{
"file": "src/cli/plugins-config.test.ts",
"reason": "Measured ~15% faster under threads than forks on base config while keeping plugin config coverage green."
},
{
"file": "src/cli/program/register.configure.test.ts",
"reason": "Measured ~12% faster under threads than forks on base config while keeping register configure coverage green."
},
{
"file": "src/cli/program/command-tree.test.ts",
"reason": "Measured ~10% faster under threads than forks on base config while keeping command tree coverage green."
},
{
"file": "src/cli/program/register.subclis.test.ts",
"reason": "Measured ~11% faster under threads than forks on base config while keeping sub-CLI registration coverage green."
},
{
"file": "test/vitest-unit-paths.test.ts",
"reason": "Measured ~11% faster under threads than forks on base config while keeping unit path checks green."
},
{
"file": "test/scripts/check-channel-agnostic-boundaries.test.ts",
"reason": "Measured ~29% faster under threads than forks on base config while keeping channel-agnostic boundary checks green."
},
{
"file": "test/plugin-npm-release.test.ts",
"reason": "Measured ~10% faster under threads than forks on base config while keeping npm release checks green."
},
{
"file": "src/cli/daemon-cli-compat.test.ts",
"reason": "Measured ~12% faster under threads than forks on base config while keeping daemon CLI compatibility coverage green."
},
{
"file": "src/cli/program/command-registry.test.ts",
"reason": "Measured ~10% faster under threads than forks on base config while keeping command registry coverage green."
},
{
"file": "src/cli/program.force.test.ts",
"reason": "Measured ~14% faster under threads than forks on base config while keeping force option coverage green."
},
{
"file": "src/cli/cli-utils.test.ts",
"reason": "Measured ~15% faster under threads than forks on base config while keeping CLI utility coverage green."
},
{
"file": "src/cli/devices-cli.test.ts",
"reason": "Measured ~21% faster under threads than forks on base config while keeping devices CLI coverage green."
},
{
"file": "src/cli/message-secret-scope.test.ts",
"reason": "Measured ~16% faster under threads than forks on base config while keeping message secret scope coverage green."
},
{
"file": "src/cli/banner.test.ts",
"reason": "Measured ~30% faster under threads than forks on base config while keeping banner rendering coverage green."
},
{
"file": "src/cli/gateway-cli.coverage.test.ts",
"reason": "Measured ~18% faster under threads than forks on base config while keeping gateway CLI coverage green."
},
{
"file": "src/channels/plugins/actions/actions.test.ts",
"reason": "Terminates cleanly under threads, but not process forks on this host."