perf(cli): skip spawnSync wrapper for qwen serve (#5874)

The daemon host process does not need --expose-gc (global.gc() is only
used by memoryPressureMonitor inside ACP children, which independently
add --expose-gc via spawnChannel.ts). Detect `serve` as the first
positional arg and import cli.js directly in-process, eliminating one
full Node process startup (~370ms on EDR-instrumented hosts).

Use pathToFileURL() for the dynamic import so Windows drive-letter
paths are not misinterpreted as URL schemes.
This commit is contained in:
jinye 2026-06-26 07:59:07 +08:00 committed by GitHub
parent 775a20361e
commit cf9be3bd81
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 45 additions and 25 deletions

View file

@ -9,29 +9,40 @@
/**
* Production bin entry wrapper.
*
* Launches dist/cli.js with --expose-gc so that global.gc() is available
* for the memory-pressure monitor's critical-tier cleanup.
* For most commands: launches dist/cli.js with --expose-gc so that
* global.gc() is available for the memory-pressure monitor's critical-tier
* cleanup.
*
* --expose-gc only exposes the function; it has zero runtime cost.
* global.gc() is called only when RSS hits the critical threshold (0.80),
* where the 10-200 ms pause is acceptable to avoid an OOM kill.
* For `qwen serve`: imports cli.js directly in-process, skipping the
* spawnSync overhead (~370ms on EDR-instrumented hosts). The daemon host
* process never calls global.gc() only its ACP children do, and they
* independently add --expose-gc via spawnChannel.ts.
*/
import { spawnSync } from 'node:child_process';
import { fileURLToPath } from 'node:url';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { dirname, join } from 'node:path';
const __dirname = dirname(fileURLToPath(import.meta.url));
const cliPath = join(__dirname, '..', 'dist', 'cli.js');
const result = spawnSync(
process.execPath,
['--expose-gc', cliPath, ...process.argv.slice(2)],
{ stdio: 'inherit' },
);
if (result.signal) {
process.kill(process.pid, result.signal);
} else {
process.exit(result.status ?? 1);
function isServeCommand() {
return process.argv[2] === 'serve';
}
if (isServeCommand()) {
process.argv[1] = cliPath;
await import(pathToFileURL(cliPath).href);
} else {
const result = spawnSync(
process.execPath,
['--expose-gc', cliPath, ...process.argv.slice(2)],
{ stdio: 'inherit' },
);
if (result.signal) {
process.kill(process.pid, result.signal);
} else {
process.exit(result.status ?? 1);
}
}

View file

@ -301,22 +301,31 @@ function writeDistPackageJson(
const cliEntryContent = `#!/usr/bin/env node
import { spawnSync } from 'node:child_process';
import { fileURLToPath } from 'node:url';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { dirname, join } from 'node:path';
const __dirname = dirname(fileURLToPath(import.meta.url));
const cliPath = join(__dirname, 'cli.js');
const result = spawnSync(
process.execPath,
['--expose-gc', cliPath, ...process.argv.slice(2)],
{ stdio: 'inherit' },
);
function isServeCommand() {
return process.argv[2] === 'serve';
}
if (result.signal) {
process.kill(process.pid, result.signal);
if (isServeCommand()) {
process.argv[1] = cliPath;
await import(pathToFileURL(cliPath).href);
} else {
process.exit(result.status ?? 1);
const result = spawnSync(
process.execPath,
['--expose-gc', cliPath, ...process.argv.slice(2)],
{ stdio: 'inherit' },
);
if (result.signal) {
process.kill(process.pid, result.signal);
} else {
process.exit(result.status ?? 1);
}
}
`;