From a93ec674e9fff1086a08cd6eccf45767f72da34c Mon Sep 17 00:00:00 2001 From: jinye Date: Sat, 27 Jun 2026 22:19:29 +0800 Subject: [PATCH] perf(cli): enable compile cache and defer getCliVersion for serve (#5938) Enable Node.js compile cache (module.enableCompileCache) in the serve fast-path so V8 bytecode is cached across daemon restarts. Start getCliVersion() as a non-blocking promise and resolve it in parallel with the runtime module loads inside buildRuntime(), removing it from the pre-listen critical path. --- packages/cli/src/serve/run-qwen-serve.ts | 22 ++++++++++++++-------- scripts/cli-entry.js | 2 ++ scripts/prepare-package.js | 2 ++ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/packages/cli/src/serve/run-qwen-serve.ts b/packages/cli/src/serve/run-qwen-serve.ts index 4e88b7670b..2aed64c062 100644 --- a/packages/cli/src/serve/run-qwen-serve.ts +++ b/packages/cli/src/serve/run-qwen-serve.ts @@ -1404,7 +1404,8 @@ export async function runQwenServe( QWEN_SERVE_MCP_BUDGET_MODE: opts.mcpBudgetMode, }; - const cliVersion = await getCliVersion(); + const cliVersionPromise = getCliVersion(); + let cliVersion: string | undefined; const diagnosticSink = (line: string, level?: 'info' | 'warn' | 'error') => daemonLog.raw(line, level); @@ -1477,11 +1478,14 @@ export async function runQwenServe( app: Application; bridge: AcpSessionBridge; }> => { - const [runtime, core, settingsRuntime] = await Promise.all([ - loadServeRuntimeModules(), - loadCoreRuntime(), - loadSettingsRuntimeModules(), - ]); + const [runtime, core, settingsRuntime, resolvedCliVersion] = + await Promise.all([ + loadServeRuntimeModules(), + loadCoreRuntime(), + loadSettingsRuntimeModules(), + cliVersionPromise, + ]); + cliVersion = resolvedCliVersion; let runtimeBootSettings: | ReturnType | undefined; @@ -1530,7 +1534,7 @@ export async function runQwenServe( core.initializeTelemetry( createDaemonTelemetryRuntimeConfig( daemonTelemetrySettings, - cliVersion, + resolvedCliVersion, `daemon:${daemonWorkspaceHash}:${process.pid}`, { otlpEndpoint: core.DEFAULT_OTLP_ENDPOINT, @@ -1755,7 +1759,7 @@ export async function runQwenServe( bridge, webShellDir, boundWorkspace, - qwenCodeVersion: cliVersion, + qwenCodeVersion: resolvedCliVersion, startup, fsFactory, daemonLog, @@ -1814,6 +1818,8 @@ export async function runQwenServe( markRuntimeReady(); } + cliVersion ??= await cliVersionPromise; + const bootstrapApp = createBootstrapServeApp({ opts, getPort: () => actualPort, diff --git a/scripts/cli-entry.js b/scripts/cli-entry.js index ad0a5ab3a3..53d44b26de 100755 --- a/scripts/cli-entry.js +++ b/scripts/cli-entry.js @@ -19,6 +19,7 @@ * independently add --expose-gc via spawnChannel.ts. */ +import module from 'node:module'; import { spawnSync } from 'node:child_process'; import { fileURLToPath, pathToFileURL } from 'node:url'; import { dirname, join } from 'node:path'; @@ -31,6 +32,7 @@ function isServeCommand() { } if (isServeCommand()) { + module.enableCompileCache?.(); process.argv[1] = cliPath; await import(pathToFileURL(cliPath).href); } else { diff --git a/scripts/prepare-package.js b/scripts/prepare-package.js index 588811d2d7..7b14fb944e 100644 --- a/scripts/prepare-package.js +++ b/scripts/prepare-package.js @@ -300,6 +300,7 @@ function writeDistPackageJson( console.log('Creating package.json for distribution...'); const cliEntryContent = `#!/usr/bin/env node +import module from 'node:module'; import { spawnSync } from 'node:child_process'; import { fileURLToPath, pathToFileURL } from 'node:url'; import { dirname, join } from 'node:path'; @@ -312,6 +313,7 @@ function isServeCommand() { } if (isServeCommand()) { + module.enableCompileCache?.(); process.argv[1] = cliPath; await import(pathToFileURL(cliPath).href); } else {