perf: speed up local heavy checks

This commit is contained in:
Peter Steinberger
2026-04-06 14:56:46 +01:00
parent b16e0df5f8
commit f3cc8d12d6
3 changed files with 102 additions and 16 deletions

View File

@@ -3,12 +3,15 @@ import fs from "node:fs";
import os from "node:os";
import path from "node:path";
const GIB = 1024 ** 3;
const DEFAULT_LOCAL_GO_GC = "30";
const DEFAULT_LOCAL_GO_MEMORY_LIMIT = "3GiB";
const DEFAULT_LOCK_TIMEOUT_MS = 10 * 60 * 1000;
const DEFAULT_LOCK_POLL_MS = 500;
const DEFAULT_LOCK_PROGRESS_MS = 15 * 1000;
const DEFAULT_STALE_LOCK_MS = 30 * 1000;
const DEFAULT_FAST_LOCAL_CHECK_MIN_MEMORY_BYTES = 48 * GIB;
const DEFAULT_FAST_LOCAL_CHECK_MIN_CPUS = 12;
const SLEEP_BUFFER = new Int32Array(new SharedArrayBuffer(4));
export function isLocalCheckEnabled(env) {
@@ -20,7 +23,7 @@ export function hasFlag(args, name) {
return args.some((arg) => arg === name || arg.startsWith(`${name}=`));
}
export function applyLocalTsgoPolicy(args, env) {
export function applyLocalTsgoPolicy(args, env, hostResources) {
const nextEnv = { ...env };
const nextArgs = [...args];
@@ -28,14 +31,16 @@ export function applyLocalTsgoPolicy(args, env) {
return { env: nextEnv, args: nextArgs };
}
insertBeforeSeparator(nextArgs, "--singleThreaded");
insertBeforeSeparator(nextArgs, "--checkers", "1");
if (shouldThrottleLocalHeavyChecks(nextEnv, hostResources)) {
insertBeforeSeparator(nextArgs, "--singleThreaded");
insertBeforeSeparator(nextArgs, "--checkers", "1");
if (!nextEnv.GOGC) {
nextEnv.GOGC = DEFAULT_LOCAL_GO_GC;
}
if (!nextEnv.GOMEMLIMIT) {
nextEnv.GOMEMLIMIT = DEFAULT_LOCAL_GO_MEMORY_LIMIT;
if (!nextEnv.GOGC) {
nextEnv.GOGC = DEFAULT_LOCAL_GO_GC;
}
if (!nextEnv.GOMEMLIMIT) {
nextEnv.GOMEMLIMIT = DEFAULT_LOCAL_GO_MEMORY_LIMIT;
}
}
if (nextEnv.OPENCLAW_TSGO_PPROF_DIR && !hasFlag(nextArgs, "--pprofDir")) {
insertBeforeSeparator(nextArgs, "--pprofDir", nextEnv.OPENCLAW_TSGO_PPROF_DIR);
@@ -44,20 +49,40 @@ export function applyLocalTsgoPolicy(args, env) {
return { env: nextEnv, args: nextArgs };
}
export function applyLocalOxlintPolicy(args, env) {
export function applyLocalOxlintPolicy(args, env, hostResources) {
const nextEnv = { ...env };
const nextArgs = [...args];
insertBeforeSeparator(nextArgs, "--type-aware");
insertBeforeSeparator(nextArgs, "--tsconfig", "tsconfig.oxlint.json");
if (isLocalCheckEnabled(nextEnv)) {
if (shouldThrottleLocalHeavyChecks(nextEnv, hostResources)) {
insertBeforeSeparator(nextArgs, "--threads=1");
}
return { env: nextEnv, args: nextArgs };
}
export function shouldThrottleLocalHeavyChecks(env, hostResources) {
if (!isLocalCheckEnabled(env)) {
return false;
}
const mode = readLocalCheckMode(env);
if (mode === "throttled") {
return true;
}
if (mode === "full") {
return false;
}
const resolvedHostResources = resolveHostResources(hostResources);
return (
resolvedHostResources.totalMemoryBytes < DEFAULT_FAST_LOCAL_CHECK_MIN_MEMORY_BYTES ||
resolvedHostResources.logicalCpuCount < DEFAULT_FAST_LOCAL_CHECK_MIN_CPUS
);
}
export function acquireLocalHeavyCheckLockSync(params) {
const env = params.env ?? process.env;
@@ -174,6 +199,29 @@ function insertBeforeSeparator(args, ...items) {
args.splice(insertIndex, 0, ...items);
}
function readLocalCheckMode(env) {
const raw = env.OPENCLAW_LOCAL_CHECK_MODE?.trim().toLowerCase();
if (raw === "throttled" || raw === "low-memory") {
return "throttled";
}
if (raw === "full" || raw === "fast") {
return "full";
}
return "auto";
}
function resolveHostResources(hostResources) {
if (hostResources) {
return hostResources;
}
return {
totalMemoryBytes: os.totalmem(),
logicalCpuCount:
typeof os.availableParallelism === "function" ? os.availableParallelism() : os.cpus().length,
};
}
function readPositiveInt(rawValue, fallback) {
const parsed = Number.parseInt(rawValue ?? "", 10);
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;