From 7b47f6b3e0ac7553f3d86b960afce20c59f3ef00 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 23 Oct 2026 13:01:53 +0000 Subject: [PATCH] perf: run Biome's binary directly rather than through its launcher `@biomejs/biome`'s bin is a Node script that starts the binary published for the platform. Run through it, every lint started a Node process only to start another one. The binary is found as the launcher finds it: what `BIOME_BINARY` names, or the build for this platform (the musl one on musl) resolved from the launcher, whose optional dependency it is. Where none is found, the launcher runs as before. Isolated: 73-105 ms per run through the launcher, 38-41 ms directly. 1,500 files, watch, a leaf edited: rebuilds ~1000-1150 ms -> ~840-960 ms. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01App18sYbe6Vf6HDCjCXbvf --- .changeset/biome-native-binary.md | 5 +++ README.md | 4 ++ src/checks/biome.js | 75 ++++++++++++++++++++++++++++++- src/cli.js | 9 ++-- test/biome/native.test.js | 50 +++++++++++++++++++++ types/checks/biome.d.ts | 9 ++++ types/cli.d.ts | 4 +- 7 files changed, 150 insertions(+), 6 deletions(-) create mode 100644 .changeset/biome-native-binary.md create mode 100644 test/biome/native.test.js diff --git a/.changeset/biome-native-binary.md b/.changeset/biome-native-binary.md new file mode 100644 index 00000000..72abc19e --- /dev/null +++ b/.changeset/biome-native-binary.md @@ -0,0 +1,5 @@ +--- +"diagnostics-webpack-plugin": patch +--- + +Run Biome's binary directly rather than through its Node launcher, which started a Node process of its own on every run only to start the binary. diff --git a/README.md b/README.md index a59d4550..8357b3a2 100644 --- a/README.md +++ b/README.md @@ -772,6 +772,10 @@ new DiagnosticsPlugin({ checks: ["biome"] }); Like the oxlint check this runs a binary and reads the JSON it answers with, which Biome calls an experimental reporter — a release of its own may move the shape, and it is the only reporter carrying the severities this check needs. +The binary is the one published for the platform beside `@biomejs/biome`, or +what `BIOME_BINARY` names, as Biome's own launcher finds it — run directly +rather than through that launcher, which is a Node process of its own on every +run for nothing but to start it. Biome's project and types rules — `noImportCycles`, `noFloatingPromises` — answer for a file from the files it imports, and which rules those are is not diff --git a/src/checks/biome.js b/src/checks/biome.js index 2d49f578..c15523f3 100644 --- a/src/checks/biome.js +++ b/src/checks/biome.js @@ -67,6 +67,75 @@ function formatDiagnostic(filename, diagnostic) { return `${filename}${at} ${diagnostic.severity} ${diagnostic.message}${rule}`; } +/** @type {Map} */ +const natives = new Map(); + +// Where each platform's build of Biome is published, as Biome's own launcher +// names them. +/** @type {Record>} */ +const PLATFORMS = { + win32: { + x64: "@biomejs/cli-win32-x64/biome.exe", + arm64: "@biomejs/cli-win32-arm64/biome.exe", + }, + darwin: { + x64: "@biomejs/cli-darwin-x64/biome", + arm64: "@biomejs/cli-darwin-arm64/biome", + }, + linux: { + x64: "@biomejs/cli-linux-x64/biome", + arm64: "@biomejs/cli-linux-arm64/biome", + }, + "linux-musl": { + x64: "@biomejs/cli-linux-x64-musl/biome", + arm64: "@biomejs/cli-linux-arm64-musl/biome", + }, +}; + +/** + * @param {string} script the launcher + * @returns {string | undefined} the binary published for this platform beside it + */ +function lookUpNative(script) { + // Node built against glibc says which one; on musl it says nothing. + const { header } = /** @type {EXPECTED_ANY} */ (process.report.getReport()); + const platform = + process.platform === "linux" && !header.glibcVersionRuntime + ? "linux-musl" + : process.platform; + const published = PLATFORMS[platform] && PLATFORMS[platform][process.arch]; + + if (!published) return undefined; + + try { + // Resolved from the launcher, whose optional dependency the build is. + return createRequire(script).resolve(published); + } catch { + return undefined; + } +} + +/** + * The binary Biome's launcher would run, found as the launcher finds it: what + * `BIOME_BINARY` names, or the build published for this platform beside the + * package. The launcher is a Node process of its own on every run, for nothing + * but to start this one. + * @param {string} script the launcher + * @returns {string | undefined} the binary, or nothing where none is found + */ +function findNative(script) { + if (process.env.BIOME_BINARY) return process.env.BIOME_BINARY; + + // Asked by every compilation, and the answer is the machine's. + if (natives.has(script)) return natives.get(script); + + const found = lookUpNative(script); + + natives.set(script, found); + + return found; +} + /** * @param {CheckContext} context check context * @returns {Promise} biome check @@ -76,6 +145,7 @@ async function create({ options }) { String(options.biomePath || "@biomejs/biome"), "biome", ); + const native = findNative(script); const cwd = String(options.context); const flags = [ String(options.command || "lint"), @@ -96,9 +166,10 @@ async function create({ options }) { for (let i = 0; i < files.length; i += FILES_PER_RUN) { const answer = await runJson( - script, + native || script, [...flags, ...files.slice(i, i + FILES_PER_RUN)], cwd, + Boolean(native), ); found.push(...(answer.diagnostics || [])); @@ -169,3 +240,5 @@ export default { // of those rules can write `readsAcrossFiles: false`. readsAcrossFiles: () => true, }; + +export { findNative }; diff --git a/src/cli.js b/src/cli.js index 4e8cbf66..7da961e3 100644 --- a/src/cli.js +++ b/src/cli.js @@ -35,16 +35,17 @@ function findBinary(specifier, binary) { * Runs a tool and reads the JSON it answers with on stdout. A tool that found * something answers non-zero, which is not a failure to run; an empty answer * with one is. - * @param {string} script the entry to run + * @param {string} script the entry to run, a script Node runs or a binary * @param {string[]} args what to run it with * @param {string} cwd where to run it + * @param {boolean=} native whether the entry is a binary run on its own * @returns {Promise} what it answered */ -function runJson(script, args, cwd) { +function runJson(script, args, cwd, native = false) { return new Promise((promiseResolve, reject) => { execFile( - process.execPath, - [script, ...args], + native ? script : process.execPath, + native ? args : [script, ...args], { cwd, maxBuffer: OUTPUT_LIMIT }, (error, stdout) => { if (!stdout && error) { diff --git a/test/biome/native.test.js b/test/biome/native.test.js new file mode 100644 index 00000000..6f450302 --- /dev/null +++ b/test/biome/native.test.js @@ -0,0 +1,50 @@ +import assert from "node:assert/strict"; +import { existsSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { createRequire } from "node:module"; +import { tmpdir } from "node:os"; +import { basename, join } from "node:path"; +import { afterEach, describe, it } from "node:test"; + +import { findNative } from "../../src/checks/biome.js"; + +const require = createRequire(import.meta.url); +const launcher = join( + require.resolve("@biomejs/biome/package.json"), + "..", + "bin", + "biome", +); + +describe("biome binary", () => { + afterEach(() => { + delete process.env.BIOME_BINARY; + }); + + it("should run the build published for this platform rather than its launcher", () => { + const found = /** @type {string} */ (findNative(launcher)); + + assert.ok(existsSync(found), found); + assert.match(basename(found), /^biome(?:\.exe)?$/u); + assert.match(found, /@biomejs[\\/]cli-/u); + }); + + it("should run what BIOME_BINARY names, as the launcher does", () => { + process.env.BIOME_BINARY = "/opt/biome"; + + assert.strictEqual(findNative(launcher), "/opt/biome"); + }); + + it("should leave a launcher with no build beside it to run itself", () => { + const alone = mkdtempSync(join(tmpdir(), "biome-alone-")); + + try { + const script = join(alone, "biome"); + + writeFileSync(script, ""); + + assert.strictEqual(findNative(script), undefined); + } finally { + rmSync(alone, { recursive: true, force: true }); + } + }); +}); diff --git a/types/checks/biome.d.ts b/types/checks/biome.d.ts index 64dc9c39..e69931f9 100644 --- a/types/checks/biome.d.ts +++ b/types/checks/biome.d.ts @@ -61,3 +61,12 @@ export type Diagnostic = { * @returns {Promise} biome check */ declare function create({ options }: CheckContext): Promise; +/** + * The binary Biome's launcher would run, found as the launcher finds it: what + * `BIOME_BINARY` names, or the build published for this platform beside the + * package. The launcher is a Node process of its own on every run, for nothing + * but to start this one. + * @param {string} script the launcher + * @returns {string | undefined} the binary, or nothing where none is found + */ +export function findNative(script: string): string | undefined; diff --git a/types/cli.d.ts b/types/cli.d.ts index 6e456bc4..b9d19a28 100644 --- a/types/cli.d.ts +++ b/types/cli.d.ts @@ -53,15 +53,17 @@ export function groupByFile( * Runs a tool and reads the JSON it answers with on stdout. A tool that found * something answers non-zero, which is not a failure to run; an empty answer * with one is. - * @param {string} script the entry to run + * @param {string} script the entry to run, a script Node runs or a binary * @param {string[]} args what to run it with * @param {string} cwd where to run it + * @param {boolean=} native whether the entry is a binary run on its own * @returns {Promise} what it answered */ export function runJson( script: string, args: string[], cwd: string, + native?: boolean | undefined, ): Promise; /** * Splits a file's diagnostics by the severity the tool gave them, so that