From 275215f7bcdcba82ad3d4227ef65b3213de2fe7a Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Mon, 10 Nov 2025 13:39:08 +0100 Subject: [PATCH] benchmark: use typescript for import cjs benchmark The original benchmark uses a not very realistic fixture (it has a huge try-catch block that would throw on the first line and then export at the end, hardly representative of real-world code). Also, it measures the entire import including evaluation, not just parsing. This updates the name to import-cjs to be more accurate, and use the typescript.js as the fixture which has been reported to be slow to import, leading users to use require() to work around the peformance impact. It splits the measurement into two different types: parsing CJS for the first time (where the overhead of loading the lexer makes a difference) and parsing CJS after the lexer has been loaded. PR-URL: https://github.com/nodejs/node/pull/60663 Refs: https://github.com/nodejs/node/issues/59913 Reviewed-By: Geoffrey Booth Reviewed-By: Yagiz Nizipli Reviewed-By: Luigi Pinca --- benchmark/esm/cjs-parse.js | 39 ----------------------------------- benchmark/esm/import-cjs.js | 41 +++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 39 deletions(-) delete mode 100644 benchmark/esm/cjs-parse.js create mode 100644 benchmark/esm/import-cjs.js diff --git a/benchmark/esm/cjs-parse.js b/benchmark/esm/cjs-parse.js deleted file mode 100644 index 13516a93133..00000000000 --- a/benchmark/esm/cjs-parse.js +++ /dev/null @@ -1,39 +0,0 @@ -'use strict'; -const fs = require('fs'); -const path = require('path'); -const common = require('../common.js'); -const { strictEqual } = require('assert'); - -const tmpdir = require('../../test/common/tmpdir'); -const benchmarkDirectory = tmpdir.resolve('benchmark-esm-parse'); - -const bench = common.createBenchmark(main, { - n: [1e2], -}); - -async function main({ n }) { - tmpdir.refresh(); - - fs.mkdirSync(benchmarkDirectory); - - let sampleSource = 'try {\n'; - for (let i = 0; i < 1000; i++) { - sampleSource += 'sample.js(() => file = /test/);\n'; - } - sampleSource += '} catch {}\nexports.p = 5;\n'; - - for (let i = 0; i < n; i++) { - const sampleFile = path.join(benchmarkDirectory, `sample${i}.js`); - fs.writeFileSync(sampleFile, sampleSource); - } - - bench.start(); - for (let i = 0; i < n; i++) { - const sampleFile = path.join(benchmarkDirectory, `sample${i}.js`); - const m = await import('file:' + sampleFile); - strictEqual(m.p, 5); - } - bench.end(n); - - tmpdir.refresh(); -} diff --git a/benchmark/esm/import-cjs.js b/benchmark/esm/import-cjs.js new file mode 100644 index 00000000000..e3d4e19e476 --- /dev/null +++ b/benchmark/esm/import-cjs.js @@ -0,0 +1,41 @@ +'use strict'; +const common = require('../common.js'); +const assert = require('assert'); +const tmpdir = require('../../test/common/tmpdir'); +const fixtures = require('../../test/common/fixtures.js'); +const fs = require('fs'); + +// This fixture has 2000+ exports. +const fixtureFile = fixtures.path('snapshot', 'typescript.js'); +// This is fixed - typescript.js is slow to load, so 10 is enough. +// And we want to measure either 10 warm loads, or 1 cold load (but compare.js would run it many times) +const runs = 10; +const bench = common.createBenchmark(main, { + type: ['cold', 'warm'], +}, { + setup() { + tmpdir.refresh(); + fs.cpSync(fixtureFile, tmpdir.resolve(`imported-cjs-initial.js`)); + for (let i = 0; i < runs; i++) { + fs.cpSync(fixtureFile, tmpdir.resolve(`imported-cjs-${i}.js`)); + } + }, +}); + +async function main({ type }) { + if (type === 'cold') { + bench.start(); + await import(tmpdir.fileURL(`imported-cjs-initial.js`)); + bench.end(1); + } else { + await import(tmpdir.fileURL(`imported-cjs-initial.js`)); // Initialize the wasm first. + bench.start(); + let result; + for (let i = 0; i < runs; i++) { + result = await import(tmpdir.fileURL(`imported-cjs-${i}.js`)); + } + bench.end(runs); + const mod = require(fixtures.path('snapshot', 'typescript.js')); + assert.deepStrictEqual(Object.keys(mod), Object.keys(result.default)); + } +}