From 2f5463ea52269aed0087ee6f417535a2a65f2eec Mon Sep 17 00:00:00 2001 From: Chris Tate Date: Sat, 3 Oct 2026 11:01:42 -0500 Subject: [PATCH] perf: overlap compiler identity and native driver discovery (#634) --- packages/compiler/src/index.ts | 20 ++++++++++++------- .../library/compiler-self-identity.test.ts | 4 ++-- .../src/library/compiler-self-identity.ts | 2 +- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/packages/compiler/src/index.ts b/packages/compiler/src/index.ts index 8144a3f94..a1182c34e 100644 --- a/packages/compiler/src/index.ts +++ b/packages/compiler/src/index.ts @@ -708,9 +708,20 @@ async function compileTracked( : null; let earlyCacheOptions: EarlyExecutableCacheOptions | null = null; if (outputKind === "exe") { - const implementation = await compilerImplementationIdentity(); const helperObjectRoute = opts.nativeProgramObject === true || (usesPrecompiledRuntimePack(opts, "llvm")); + // Package content and native driver discovery are independent inputs to + // the same cache key. Start both before waiting so edits do not pay their + // filesystem and subprocess latency serially. + const [implementation, nativeEnvironment] = await Promise.all([ + compilerImplementationIdentity(), + helperObjectRoute + ? executableLinkerEnvironmentFingerprint( + process.env, + nativeCodegenTarget()?.defaultLinker, + ) + : executableNativeEnvironmentFingerprint(), + ]); earlyCacheOptions = { entryPath, outDir: opts.outDir, @@ -737,12 +748,7 @@ async function compileTracked( ? resolvePlatformLinker(process.env, nativeCodegenTarget()?.defaultLinker) : (process.env["SCRIPTC_CC"] ?? "clang"), ], - nativeEnvironment: helperObjectRoute - ? await executableLinkerEnvironmentFingerprint( - process.env, - nativeCodegenTarget()?.defaultLinker, - ) - : await executableNativeEnvironmentFingerprint(), + nativeEnvironment, nodeVersion: process.version, implementation: implementation.digest, implementationDependencies: implementation.dependencies, diff --git a/packages/compiler/src/library/compiler-self-identity.test.ts b/packages/compiler/src/library/compiler-self-identity.test.ts index 050cc83e1..68a493714 100644 --- a/packages/compiler/src/library/compiler-self-identity.test.ts +++ b/packages/compiler/src/library/compiler-self-identity.test.ts @@ -27,8 +27,8 @@ test("parallel fingerprinting preserves the v1 byte stream and dependency order const files: [string, string][] = [ [join("a", "index.ts"), "export const value = 42;\n"], ["a.ts", ""], - ...Array.from({ length: 40 }, (_, i): [string, string] => [ - join("z", `file${String(i).padStart(2, "0")}.js`), + ...Array.from({ length: 140 }, (_, i): [string, string] => [ + join("z", `file${String(i).padStart(3, "0")}.js`), `// ${i}\n${"\u03bb".repeat(i * 1000)}`, ]), ]; diff --git a/packages/compiler/src/library/compiler-self-identity.ts b/packages/compiler/src/library/compiler-self-identity.ts index a5132349d..13b2c3b7c 100644 --- a/packages/compiler/src/library/compiler-self-identity.ts +++ b/packages/compiler/src/library/compiler-self-identity.ts @@ -80,7 +80,7 @@ export async function compilerImplementationIdentity( // trips on every application edit; reading the entire package at once // would retain all its bytes and open an unbounded number of files. const hash = createHash("sha256").update("scriptc-frontend-implementation-v1\0"); - const batchSize = 16; + const batchSize = 64; for (let start = 0; start < entries.length; start += batchSize) { const batch = await Promise.all(entries.slice(start, start + batchSize).map(async (entry) => { if (entry.directory !== undefined) return { ...entry, info: entry.directory, bytes: null };