From 45f0e495e7299cacd8bbfb27c6208bc3a4a6218b Mon Sep 17 00:00:00 2001 From: Alexander Akait <4567934+alexander-akait@users.noreply.github.com> Date: Wed, 30 Apr 2025 23:52:14 +0300 Subject: [PATCH] chore: add more benchmark cases (#19481) --- .github/workflows/test.yml | 5 + .gitignore | 3 +- .prettierignore | 2 + benchmark/benchmark.js | 239 ------------ benchmark/createBenchmark.js | 30 -- benchmark/createBenchmark/entry.js | 26 -- benchmark/createBenchmark/loadLoader.js | 3 - benchmark/createFixtures.js | 59 --- benchmark/createFixtures2.js | 69 ---- benchmark/createTestCases.js | 83 ----- eslint.config.mjs | 2 + package.json | 1 + test/BenchmarkTestCases.benchmark.mjs | 346 +++++++++++++----- test/benchmarkCases/_helpers/create-tree.mjs | 103 ++++++ test/benchmarkCases/cache-filesystem/index.js | 2 + .../cache-filesystem/webpack.config.js | 7 + test/benchmarkCases/context-commonjs/index.js | 6 + .../benchmarkCases/context-commonjs/setup.mjs | 11 + .../webpack.config.js | 0 test/benchmarkCases/context-esm/index.js | 5 + test/benchmarkCases/context-esm/setup.mjs | 11 + .../webpack.config.js | 0 .../devtool-eval-source-map/index.js | 2 + .../devtool-eval-source-map/setup.mjs | 11 + .../devtool-eval-source-map/webpack.config.js | 5 + test/benchmarkCases/devtool-eval/index.js | 2 + test/benchmarkCases/devtool-eval/setup.mjs | 11 + .../webpack.config.js | 3 +- test/benchmarkCases/devtool-source-map/a.js | 10 - test/benchmarkCases/devtool-source-map/b.js | 11 - test/benchmarkCases/devtool-source-map/c.js | 1 - .../devtool-source-map/index.js | 12 +- .../devtool-source-map/setup.mjs | 11 + test/benchmarkCases/future-defaults/index.js | 2 + test/benchmarkCases/future-defaults/setup.mjs | 11 + .../future-defaults/webpack.config.js | 7 + .../many-chunks-commonjs/index.js | 2 + .../many-chunks-commonjs/setup.mjs | 11 + .../many-chunks-commonjs/webpack.config.js | 4 + test/benchmarkCases/many-chunks-esm/index.js | 2 + test/benchmarkCases/many-chunks-esm/setup.mjs | 11 + .../many-chunks-esm/webpack.config.js | 4 + test/benchmarkCases/many-chunks/a.js | 10 - test/benchmarkCases/many-chunks/b.js | 6 - test/benchmarkCases/many-chunks/c.js | 1 - test/benchmarkCases/many-chunks/index.js | 10 - .../many-modules-commonjs/index.js | 2 + .../many-modules-commonjs/setup.mjs | 11 + .../many-modules-commonjs/webpack.config.js | 4 + test/benchmarkCases/many-modules-esm/index.js | 2 + .../benchmarkCases/many-modules-esm/setup.mjs | 11 + .../many-modules-esm/webpack.config.js | 4 + test/benchmarkCases/many-modules/a.js | 10 - test/benchmarkCases/many-modules/b.js | 11 - test/benchmarkCases/many-modules/c.js | 1 - test/benchmarkCases/many-modules/index.js | 10 - test/benchmarkCases/minimal/index.js | 1 + test/benchmarkCases/minimal/webpack.config.js | 4 + .../popular-libraries-long/index.js | 6 + .../popular-libraries-long/webpack.config.js | 4 + test/benchmarkCases/three-long/index.js | 2 + .../three-long/webpack.config.js | 4 + test/benchmarkCases/typescript-long/index.js | 2 + .../typescript-long/webpack.config.js | 11 + yarn.lock | 5 + 65 files changed, 579 insertions(+), 699 deletions(-) delete mode 100644 benchmark/benchmark.js delete mode 100644 benchmark/createBenchmark.js delete mode 100644 benchmark/createBenchmark/entry.js delete mode 100644 benchmark/createBenchmark/loadLoader.js delete mode 100644 benchmark/createFixtures.js delete mode 100644 benchmark/createFixtures2.js delete mode 100644 benchmark/createTestCases.js create mode 100644 test/benchmarkCases/_helpers/create-tree.mjs create mode 100644 test/benchmarkCases/cache-filesystem/index.js create mode 100644 test/benchmarkCases/cache-filesystem/webpack.config.js create mode 100644 test/benchmarkCases/context-commonjs/index.js create mode 100644 test/benchmarkCases/context-commonjs/setup.mjs rename test/benchmarkCases/{many-chunks => context-commonjs}/webpack.config.js (100%) create mode 100644 test/benchmarkCases/context-esm/index.js create mode 100644 test/benchmarkCases/context-esm/setup.mjs rename test/benchmarkCases/{many-modules => context-esm}/webpack.config.js (100%) create mode 100644 test/benchmarkCases/devtool-eval-source-map/index.js create mode 100644 test/benchmarkCases/devtool-eval-source-map/setup.mjs create mode 100644 test/benchmarkCases/devtool-eval-source-map/webpack.config.js create mode 100644 test/benchmarkCases/devtool-eval/index.js create mode 100644 test/benchmarkCases/devtool-eval/setup.mjs rename test/benchmarkCases/{popular-libraries => devtool-eval}/webpack.config.js (63%) delete mode 100644 test/benchmarkCases/devtool-source-map/a.js delete mode 100644 test/benchmarkCases/devtool-source-map/b.js delete mode 100644 test/benchmarkCases/devtool-source-map/c.js create mode 100644 test/benchmarkCases/devtool-source-map/setup.mjs create mode 100644 test/benchmarkCases/future-defaults/index.js create mode 100644 test/benchmarkCases/future-defaults/setup.mjs create mode 100644 test/benchmarkCases/future-defaults/webpack.config.js create mode 100644 test/benchmarkCases/many-chunks-commonjs/index.js create mode 100644 test/benchmarkCases/many-chunks-commonjs/setup.mjs create mode 100644 test/benchmarkCases/many-chunks-commonjs/webpack.config.js create mode 100644 test/benchmarkCases/many-chunks-esm/index.js create mode 100644 test/benchmarkCases/many-chunks-esm/setup.mjs create mode 100644 test/benchmarkCases/many-chunks-esm/webpack.config.js delete mode 100644 test/benchmarkCases/many-chunks/a.js delete mode 100644 test/benchmarkCases/many-chunks/b.js delete mode 100644 test/benchmarkCases/many-chunks/c.js delete mode 100644 test/benchmarkCases/many-chunks/index.js create mode 100644 test/benchmarkCases/many-modules-commonjs/index.js create mode 100644 test/benchmarkCases/many-modules-commonjs/setup.mjs create mode 100644 test/benchmarkCases/many-modules-commonjs/webpack.config.js create mode 100644 test/benchmarkCases/many-modules-esm/index.js create mode 100644 test/benchmarkCases/many-modules-esm/setup.mjs create mode 100644 test/benchmarkCases/many-modules-esm/webpack.config.js delete mode 100644 test/benchmarkCases/many-modules/a.js delete mode 100644 test/benchmarkCases/many-modules/b.js delete mode 100644 test/benchmarkCases/many-modules/c.js delete mode 100644 test/benchmarkCases/many-modules/index.js create mode 100644 test/benchmarkCases/minimal/index.js create mode 100644 test/benchmarkCases/minimal/webpack.config.js create mode 100644 test/benchmarkCases/popular-libraries-long/index.js create mode 100644 test/benchmarkCases/popular-libraries-long/webpack.config.js create mode 100644 test/benchmarkCases/three-long/index.js create mode 100644 test/benchmarkCases/three-long/webpack.config.js create mode 100644 test/benchmarkCases/typescript-long/index.js create mode 100644 test/benchmarkCases/typescript-long/webpack.config.js diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a0583c726..6c6232cb4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -60,6 +60,10 @@ jobs: - run: node -e "const content = require('./package.json');delete content.devDependencies;require('fs').writeFileSync('package.json', JSON.stringify(content, null, 2));" - run: yarn install --production --frozen-lockfile benchmark: + strategy: + fail-fast: false + matrix: + shard: [1/4, 2/4, 3/4, 4/4] runs-on: ubuntu-latest permissions: issues: write @@ -84,6 +88,7 @@ jobs: token: ${{ secrets.CODSPEED_TOKEN }} env: CODSPEED: 1 + SHARD: ${{ matrix.shard }} basic: runs-on: ubuntu-latest steps: diff --git a/.gitignore b/.gitignore index a525ff449..20ee74c93 100644 --- a/.gitignore +++ b/.gitignore @@ -5,8 +5,7 @@ /test/temp /test/ChangesAndRemovals /test/**/dev-defaults.webpack.lock -/benchmark/js -/benchmark/fixtures +/test/**/generated/** /examples/**/dist /examples/nodejs-addons/build/** /assembly/**/*.wat diff --git a/.prettierignore b/.prettierignore index c70d7844b..bfc2b2620 100644 --- a/.prettierignore +++ b/.prettierignore @@ -14,6 +14,8 @@ test/**/*.* !test/**/infrastructure-log.js !test/*.md !test/helpers/*.* +!test/benchmarkCases/**/*.mjs +!test/_helpers/**/*.mjs test/js/**/*.* # Ignore some folders diff --git a/benchmark/benchmark.js b/benchmark/benchmark.js deleted file mode 100644 index 7e246b072..000000000 --- a/benchmark/benchmark.js +++ /dev/null @@ -1,239 +0,0 @@ -const path = require("path"); -const fs = require("fs"); -const Benchmark = require("benchmark"); -const webpack = require("../"); -const fixtures = path.join(__dirname, "fixtures"); -const outputPath = path.join(__dirname, "js"); - -const benchmarkOptions = { - defer: true, - onCycle: function () { - process.stderr.write("."); - }, - minSamples: 10 -}; - -function runTimes(compiler, times, deferred) { - fs.writeFileSync( - path.join(fixtures, "0.js"), - "module.exports = " + Math.random(), - "utf-8" - ); - compiler.run(err => { - if (err) throw err; - if (times === 1) deferred.resolve(); - else runTimes(compiler, times - 1, deferred); - }); -} - -const tests = { - "normal build": [ - [0, 1, 5, 10, 50, 100, 200], - (size, deferred) => { - webpack( - { - context: fixtures, - entry: `./${size}.js`, - output: { - path: outputPath, - filename: "bundle.js" - } - }, - err => { - if (err) throw err; - deferred.resolve(); - } - ); - } - ], - "eval dev build": [ - [0, 1, 2, 5, 10, 15], - (size, deferred) => { - webpack( - { - context: fixtures, - entry: `./${size}.big.js`, - output: { - path: outputPath, - filename: "bundle.js" - }, - devtool: "eval" - }, - err => { - if (err) throw err; - deferred.resolve(); - } - ); - } - ], - "sourcemap build": [ - [0, 1, 2, 5, 10, 15], - (size, deferred) => { - webpack( - { - context: fixtures, - entry: `./${size}.big.js`, - output: { - path: outputPath, - filename: "bundle.js" - }, - devtool: "source-map" - }, - err => { - if (err) throw err; - deferred.resolve(); - } - ); - } - ], - "cheap sourcemap build": [ - [0, 1, 2, 5, 10, 15], - (size, deferred) => { - webpack( - { - context: fixtures, - entry: `./${size}.big.js`, - output: { - path: outputPath, - filename: "bundle.js" - }, - devtool: "cheap-source-map" - }, - err => { - if (err) throw err; - deferred.resolve(); - } - ); - } - ], - "build w/ chunks": [ - [0, 1, 5, 10, 50, 100, 200], - (size, deferred) => { - webpack( - { - context: fixtures, - entry: `./${size}.async.js`, - output: { - path: outputPath, - filename: "bundle.js" - } - }, - err => { - if (err) throw err; - deferred.resolve(); - } - ); - } - ], - incremental: [ - [0, 1, 5, 10, 50, 100, 200], - (size, deferred) => { - var compiler = webpack({ - cache: true, - context: fixtures, - entry: "./" + size + ".js", - output: { - path: outputPath, - filename: "bundle.js" - } - }); - runTimes(compiler, 2, deferred); - } - ], - "incremental cheap sourcemap": [ - [1, 2, 3, 4, 5, 6], - (size, deferred) => { - var compiler = webpack({ - cache: true, - context: fixtures, - entry: "./200.js", - output: { - path: outputPath, - filename: "bundle.js" - }, - devtool: "cheap-source-map" - }); - runTimes(compiler, size, deferred); - } - ], - incremental2: [ - [0, 1, 5, 10, 50, 100, 200], - (size, deferred) => { - var compiler = webpack({ - cache: true, - context: fixtures, - entry: `./${size}.js`, - output: { - path: outputPath, - filename: "bundle.js" - } - }); - runTimes(compiler, 3, deferred); - } - ], - incremental4: [ - [0, 1, 5, 10, 50, 100, 200], - (size, deferred) => { - var compiler = webpack({ - cache: true, - context: fixtures, - entry: `./${size}.js`, - output: { - path: outputPath, - filename: "bundle.js" - } - }); - runTimes(compiler, 5, deferred); - } - ], - incremental16: [ - [0, 1, 5, 10, 50, 100, 200], - (size, deferred) => { - var compiler = webpack({ - cache: true, - context: fixtures, - entry: `./${size}.js`, - output: { - path: outputPath, - filename: "bundle.js" - } - }); - runTimes(compiler, 17, deferred); - } - ] -}; - -const suite = new Benchmark.Suite(); - -Object.keys(tests) - .filter(name => - process.argv.length > 2 ? name.includes(process.argv[2]) : true - ) - .forEach(name => { - const test = tests[name]; - test[0].forEach(size => { - suite.add( - `${name} ${size}`, - deferred => { - test[1](size, deferred); - }, - benchmarkOptions - ); - }); - }); - -suite.on("cycle", event => { - process.stderr.write("\n"); - const b = event.target; - console.log( - b.name + - "\t" + - Math.floor(1000 * (b.stats.mean - b.stats.moe)) + - "\t" + - Math.floor(1000 * (b.stats.mean + b.stats.moe)) - ); -}); - -suite.run({ - async: true -}); diff --git a/benchmark/createBenchmark.js b/benchmark/createBenchmark.js deleted file mode 100644 index f48822502..000000000 --- a/benchmark/createBenchmark.js +++ /dev/null @@ -1,30 +0,0 @@ -const webpack = require("../"); -const path = require("path"); - -webpack( - { - context: __dirname, - entry: "./createBenchmark/entry.js", - output: { - path: __dirname, - filename: "benchmark-bundle.js" - }, - target: "node", - node: { - __dirname: false - }, - optimization: { - moduleIds: "named" - }, - plugins: [ - new webpack.IgnorePlugin(/^(fsevents|terser)$/), - new webpack.NormalModuleReplacementPlugin( - /^.\/loadLoader$/, - path.resolve(__dirname, "./createBenchmark/loadLoader") - ) - ] - }, - (err, stats) => { - console.log(stats.toString()); - } -); diff --git a/benchmark/createBenchmark/entry.js b/benchmark/createBenchmark/entry.js deleted file mode 100644 index 0f8bb1395..000000000 --- a/benchmark/createBenchmark/entry.js +++ /dev/null @@ -1,26 +0,0 @@ -const webpack = require("../../"); -const path = require("path"); - -const testCase = process.argv[2]; - -const config = { - context: __dirname, - entry: `./${testCase}`, - output: { - path: path.resolve(__dirname, "output-" + testCase) - }, - devtool: process.argv[3] -}; - -const compiler = webpack(config); -compiler.run((err, stats) => { - if (err) { - console.error(err); - } else { - console.log( - stats.toString({ - errorDetails: true - }) - ); - } -}); diff --git a/benchmark/createBenchmark/loadLoader.js b/benchmark/createBenchmark/loadLoader.js deleted file mode 100644 index 782405291..000000000 --- a/benchmark/createBenchmark/loadLoader.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = (loader, callback) => { - callback(new Error("Loaders are not supported")); -}; diff --git a/benchmark/createFixtures.js b/benchmark/createFixtures.js deleted file mode 100644 index 2bb50be73..000000000 --- a/benchmark/createFixtures.js +++ /dev/null @@ -1,59 +0,0 @@ -const path = require("path"); -const fs = require("fs"); - -const fixtures = path.join(__dirname, "fixtures"); - -try { - fs.mkdirSync(fixtures); -} catch (e) { - // The directory already exists -} - -function generateRequireString(conditional, suffix) { - const prefixedSuffix = suffix ? `.${suffix}` : ""; - return `require(${JSON.stringify(`./${conditional}${prefixedSuffix}.js`)});`; -} - -for (let i = 0; i < 10000; i++) { - const source = []; - if (i > 8) source.push(generateRequireString((i / 8) | 0)); - if (i > 4) source.push(generateRequireString((i / 4) | 0)); - if (i > 2) source.push(generateRequireString((i / 2) | 0)); - if (i > 0) source.push(generateRequireString(i - 1)); - source.push("module.exports = " + i + ";"); - fs.writeFileSync(path.join(fixtures, i + ".js"), source.join("\n"), "utf-8"); -} - -for (let i = 0; i < 10000; i++) { - const source = []; - source.push("require.ensure([], function(require) {"); - if (i > 8) source.push(generateRequireString((i / 8) | 0, "async")); - if (i > 4) source.push(generateRequireString((i / 4) | 0, "async")); - if (i > 2) source.push(generateRequireString((i / 2) | 0, "async")); - if (i > 0) source.push(generateRequireString(i - 1, "async")); - source.push("});"); - source.push("module.exports = " + i + ";"); - fs.writeFileSync( - path.join(fixtures, i + ".async.js"), - source.join("\n"), - "utf-8" - ); -} - -for (let i = 0; i < 100; i++) { - const source = []; - if (i > 8) source.push(generateRequireString((i / 8) | 0, "big")); - if (i > 4) source.push(generateRequireString((i / 4) | 0, "big")); - if (i > 2) source.push(generateRequireString((i / 2) | 0, "big")); - if (i > 0) source.push(generateRequireString(i - 1, "big")); - for (let j = 0; j < 300; j++) - source.push( - "if(Math.random())hello.world();test.a.b.c.d();x(1,2,3,4);var a,b,c,d,e,f;" - ); - source.push("module.exports = " + i + ";"); - fs.writeFileSync( - path.join(fixtures, i + ".big.js"), - source.join("\n"), - "utf-8" - ); -} diff --git a/benchmark/createFixtures2.js b/benchmark/createFixtures2.js deleted file mode 100644 index 833f790b1..000000000 --- a/benchmark/createFixtures2.js +++ /dev/null @@ -1,69 +0,0 @@ -const path = require("path"); -const fs = require("fs"); - -const fixtures = path.join(__dirname, "fixtures"); - -try { - fs.mkdirSync(fixtures); -} catch (e) { - // The directory already exists -} - -function genModule(prefix, depth, asyncDepth, multiplex, r, circular) { - const source = []; - const isAsync = depth >= asyncDepth; - if (!isAsync) circular.push(path.resolve(fixtures, prefix + "/index.js")); - source.push("(function() {"); - const m = (r % multiplex) + 1; - let sum = 1; - let item; - try { - fs.mkdirSync(path.resolve(fixtures, prefix)); - } catch (e) { - // The directory already exists - } - if (depth > 0) { - for (let i = 0; i < m; i++) { - sum += genModule( - prefix + "/" + i, - depth - 1, - asyncDepth, - multiplex, - (r + i + depth) * m + i + depth, - circular - ); - source.push("require(" + JSON.stringify("./" + i) + ");"); - if (i === 0) { - if (isAsync) source.push("}); require.ensure([], function() {"); - } - } - item = circular[r % circular.length]; - } - source.push("}, " + JSON.stringify(prefix) + ");"); - if (item) source.push("require(" + JSON.stringify(item) + ");"); - source.push("module.exports = " + JSON.stringify(prefix) + ";"); - fs.writeFileSync( - path.resolve(fixtures, prefix + "/index.js"), - source.join("\n"), - "utf-8" - ); - return sum; -} - -for (let i = 2; i < 14; i++) { - const count = genModule("tree-" + i, 6, 100, i, 0, []); - console.log("generated tree", i, count); -} - -for (let i = 2; i < 14; i++) { - const count = genModule("async-tree-" + i, 6, 1, i, 0, []); - console.log("generated async tree", i, count); -} - -const a = genModule("module-async", 7, 1, 3, 2, []); - -const b = genModule("module-big-async", 5, 2, 9, 2, []); - -const c = genModule("module-broad-async", 3, 3, 20, 10, []); - -console.log("generated modules", a, b, c); diff --git a/benchmark/createTestCases.js b/benchmark/createTestCases.js deleted file mode 100644 index 3a2fc8794..000000000 --- a/benchmark/createTestCases.js +++ /dev/null @@ -1,83 +0,0 @@ -let avgJs = ` -const str = "we" + "do" + "some" + "ops"; -for(const x of str.split("")) { - if(x.charCodeAt(0) > 40) { - console.log("omg"); - } else { - console.log(Math.random() * 2 + 3 * 2); - } -} - -// Some comment -switch(a.b.c.d.f.e.g.h.i) { - case true: - break; - case "magic": - throw new Error("Error!"); - case 9: - (function() { - // extra scope - var x = 123; - var y = 456; - var z = x + z * x / y; - x && y && (z = x ? y : x); - }()) -} - -function a() {} -function b() {} -function c() {} -function d() {} -function e() {} -function f() {} -`; - -for (let i = 0; i < 2; i++) { - avgJs += `(function() {${avgJs}}());`; -} - -const fs = require("fs"); -const root = __dirname; - -createTree(fs, 100, `${root}/modules-100`); -createTree(fs, 500, `${root}/modules-500`); -createTree(fs, 1000, `${root}/modules-1000`); -createTree(fs, 3000, `${root}/modules-3000`); -createTree(fs, 5000, `${root}/modules-5000`); - -function createTree(fs, count, folder) { - fs.mkdirSync(folder); - let remaining = count - 1; - - function make(prefix, count, depth) { - if (count === 0) { - fs.writeFileSync(`${folder}/${prefix}.js`, `export default 1;\n${avgJs}`); - } else { - const list = []; - for (let i = 0; i < count; i++) { - if (remaining-- <= 0) break; - if (depth <= 4 && i >= 3 && i <= 4) { - list.push( - `const module${i} = import("./${prefix}-${i}");\ncounter += module${i};` - ); - } else { - list.push( - `import module${i} from "./${prefix}-${i}";\ncounter += module${i};` - ); - } - make( - `${prefix}-${i}`, - depth > 4 || count > 30 ? 0 : count + depth + Math.pow(i, 2), - depth + 1 - ); - } - fs.writeFileSync( - `${folder}/${prefix}.js`, - `let counter = 0;\n${list.join( - "\n" - )};\nexport default counter;\n${avgJs}` - ); - } - } - make("index", 2, 0); -} diff --git a/eslint.config.mjs b/eslint.config.mjs index 41108bf13..5004ed0b4 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -27,6 +27,8 @@ export default defineConfig([ "!test/**/deprecations.js", "!test/**/infrastructure-log.js", "!test/helpers/*.*", + "!test/benchmarkCases/**/*.mjs", + "!test/_helpers/**/*.mjs", "test/js/**/*.*", // Ignore some folders diff --git a/package.json b/package.json index ba4402181..0f6321c05 100644 --- a/package.json +++ b/package.json @@ -103,6 +103,7 @@ "strip-ansi": "^6.0.0", "style-loader": "^4.0.0", "terser": "^5.38.1", + "three": "^0.176.0", "toml": "^3.0.0", "tooling": "webpack/tooling#v1.23.7", "ts-loader": "^9.5.1", diff --git a/test/BenchmarkTestCases.benchmark.mjs b/test/BenchmarkTestCases.benchmark.mjs index b9296f22d..e77dbfa24 100644 --- a/test/BenchmarkTestCases.benchmark.mjs +++ b/test/BenchmarkTestCases.benchmark.mjs @@ -4,9 +4,8 @@ import path from "path"; import fs from "fs/promises"; import { constants } from "fs"; import Benchmark from "benchmark"; -import { remove } from "./helpers/remove.js"; import { dirname } from "path"; -import { fileURLToPath } from "url"; +import { fileURLToPath, pathToFileURL } from "url"; import simpleGit from "simple-git"; import { withCodSpeed } from "@codspeed/benchmark.js-plugin"; @@ -65,18 +64,21 @@ async function getHead(revList) { return process.env.HEAD; } + // On CI we take the latest commit `merge commit` as a head if (revList[3]) { return revList[3]; } + // Otherwise we take the latest commit return revList[1]; } /** + * @param {string} head head * @param {(string | undefined)[]} revList rev list * @returns {Promise} base */ -async function getBase(revList) { +async function getBase(head, revList) { if (typeof process.env.BASE !== "undefined") { return process.env.BASE; } @@ -102,6 +104,10 @@ async function getBase(revList) { throw new Error("No parent commit found"); } + if (head === revList[1]) { + return revList[2]; + } + return revList[1]; } @@ -134,7 +140,7 @@ async function getBaselineRevs() { ]; } - const base = await getBase(revList); + const base = await getBase(head, revList); if (!head || !base) { throw new Error("No baseline found"); @@ -200,29 +206,13 @@ for (const baselineInfo of baselineRevisions) { baselines.push({ name: baselineInfo.name, rev: baselineRevision, - webpack: async config => { + webpack: async () => { const webpack = ( await import( - path.resolve( - baselinePath, - `./lib/index.js?nocache=${Math.random()}` - ) + pathToFileURL(path.resolve(baselinePath, `./lib/index.js`)) ) ).default; - await new Promise((resolve, reject) => { - const warmupCompiler = webpack(config, (err, _stats) => { - if (err) { - reject(err); - return; - } - - warmupCompiler.purgeInputFileSystem(); - - resolve(); - }); - }); - return webpack; } }); @@ -257,52 +247,185 @@ for (const baselineInfo of baselineRevisions) { } } -async function registerBenchmarks(suite, test, baselines) { - for (const baseline of baselines) { - const outputDirectory = path.join( - __dirname, - "js", - "benchmark", - `baseline-${baseline.name}`, - test - ); - const testDirectory = path.join(casesPath, test); - const config = - ( - await import( - path.join(testDirectory, `webpack.config.js?nocache=${Math.random()}`) - ) - ).default || {}; - - config.mode = config.mode || "production"; - config.output = config.output || {}; - - if (!config.context) config.context = testDirectory; - if (!config.output.path) config.output.path = outputDirectory; - - const suiteName = `benchmark "${test}"${CODSPEED ? "" : ` ${baseline.name} (${baseline.rev})`}`; - const webpack = await baseline.webpack(config); - - suite.add(suiteName, { - baseTestName: test, - defer: true, - fn(deferred) { - const compiler = webpack(config, (err, stats) => { - compiler.purgeInputFileSystem(); - - if (err) { - throw err; - } - - if (stats.hasErrors()) { - throw new Error(stats.toString()); - } - - deferred.resolve(); - }); - } - }); +const scenarios = [ + { + name: "mode-development", + mode: "development" + }, + { + name: "mode-development-rebuild", + mode: "development", + watch: true + }, + { + name: "mode-production", + mode: "production" } +]; + +function buildConfiguration( + test, + baseline, + realConfig, + scenario, + testDirectory +) { + const { watch, ...rest } = scenario; + const config = structuredClone({ ...realConfig, ...rest }); + + config.entry = config.entry || "./index.js"; + config.devtool = config.devtool || false; + config.name = `${test}-${baseline.name}-${scenario.name}`; + config.context = testDirectory; + config.performance = false; + config.output = config.output || {}; + config.output.path = path.join( + baseOutputPath, + test, + `scenario-${scenario.name}`, + `baseline-${baseline.name}` + ); + + if (config.cache) { + config.cache.cacheDirectory = path.resolve(config.output.path, ".cache"); + } + + return config; +} + +function warmupCompiler(compiler) { + return new Promise((resolve, reject) => { + compiler.run((err, stats) => { + if (err) { + reject(err); + } + + if (stats.hasWarnings() || stats.hasErrors()) { + reject(new Error(stats.toString())); + } + + compiler.close(closeErr => { + if (closeErr) { + reject(closeErr); + } + + resolve(); + }); + }); + }); +} + +function runWatch(compiler) { + return new Promise((resolve, reject) => { + const watching = compiler.watch({}, (err, stats) => { + if (err) { + reject(err); + } + + if (stats.hasWarnings() || stats.hasErrors()) { + reject(new Error(stats.toString())); + } + + resolve(watching); + }); + }); +} + +const baseOutputPath = path.join(__dirname, "js", "benchmark"); + +async function registerSuite(suite, test, baselines) { + const testDirectory = path.join(casesPath, test); + const setupPath = path.resolve(testDirectory, "setup.mjs"); + + let needSetup = true; + + try { + await fs.access(setupPath, constants.R_OK); + } catch (_err) { + needSetup = false; + } + + if (needSetup) { + await import(`${pathToFileURL(setupPath)}?date=${Date.now()}`); + } + + const realConfig = ( + await import( + `${pathToFileURL(path.join(testDirectory, `webpack.config.js`))}` + ) + ).default; + + await Promise.all( + baselines.map(async baseline => { + const webpack = await baseline.webpack(); + + await Promise.all( + scenarios.map(async scenario => { + const config = buildConfiguration( + test, + baseline, + realConfig, + scenario, + testDirectory + ); + + // Warmup and also prebuild cache + await warmupCompiler(webpack(config)); + + // Make an extra run for watching tests + let watching; + + if (scenario.watch) { + watching = await runWatch(webpack(config)); + } + + const stringifiedScenario = JSON.stringify(scenario); + const suiteName = `benchmark "${test}", scenario '${stringifiedScenario}'${CODSPEED ? "" : ` ${baseline.name} (${baseline.rev})`}`; + const fullSuiteName = `benchmark "${test}", scenario '${stringifiedScenario}' ${baseline.name} (${baseline.rev})`; + + console.log(`Register: ${fullSuiteName}`); + + suite.add(suiteName, { + collectBy: `${test}, scenario '${stringifiedScenario}'`, + defer: true, + fn(deferred) { + if (watching) { + watching.invalidate(() => { + watching.close(closeErr => { + if (closeErr) { + throw closeErr; + } + + deferred.resolve(); + }); + }); + } else { + const baseCompiler = webpack(config); + + baseCompiler.run((err, stats) => { + if (err) { + throw err; + } + + if (stats.hasWarnings() || stats.hasErrors()) { + throw new Error(stats.toString()); + } + + baseCompiler.close(closeErr => { + if (closeErr) { + throw closeErr; + } + + deferred.resolve(); + }); + }); + } + } + }); + }) + ); + }) + ); } const suite = withCodSpeed( @@ -315,31 +438,62 @@ const suite = withCodSpeed( }) ); +await fs.rm(baseOutputPath, { recursive: true, force: true }); + const casesPath = path.join(__dirname, "benchmarkCases"); +const allBenchmarks = (await fs.readdir(casesPath)) + .filter(item => !item.includes("_")) + .sort((a, b) => a.localeCompare(b)); -const tests = []; +const benchmarks = allBenchmarks.filter(item => !item.includes("long")); +const longBenchmarks = allBenchmarks.filter(item => item.includes("long")); +const i = Math.floor(benchmarks.length / longBenchmarks.length); -for (const folder of await fs.readdir(casesPath)) { - if (folder.includes("_")) { - continue; - } - - try { - await fs.access( - path.resolve(casesPath, folder, "webpack.config.js"), - constants.R_OK - ); - } catch (_err) { - continue; - } - - tests.push(folder); +for (const [index, value] of longBenchmarks.entries()) { + benchmarks.splice(index * i, 0, value); } -for (const test of tests) { - await registerBenchmarks(suite, test, baselines); +const shard = + typeof process.env.SHARD !== "undefined" + ? process.env.SHARD.split("/").map(item => Number.parseInt(item, 10)) + : [1, 1]; + +if ( + typeof shard[0] === "undefined" || + typeof shard[1] === "undefined" || + shard[0] > shard[1] || + shard[0] <= 0 || + shard[1] <= 0 +) { + throw new Error( + `Invalid \`SHARD\` value - it should be less then a part and more than zero, shard part is ${shard[0]}, count of shards is ${shard[1]}` + ); } +function splitToNChunks(array, n) { + const result = []; + + for (let i = n; i > 0; i--) { + result.push(array.splice(0, Math.ceil(array.length / i))); + } + + return result; +} + +const countOfBenchmarks = benchmarks.length; + +if (countOfBenchmarks < shard[1]) { + throw new Error( + `Shard upper limit is more than count of benchmarks, count of benchmarks is ${countOfBenchmarks}, shard is ${shard[1]}` + ); +} + +await Promise.all( + splitToNChunks(benchmarks, shard[1])[shard[0] - 1].map(benchmark => + registerSuite(suite, benchmark, baselines) + ) +); + const statsByTests = new Map(); suite.on("cycle", event => { @@ -349,21 +503,25 @@ suite.on("cycle", event => { const nSqrt = Math.sqrt(n); const z = tDistribution(n - 1); - stats.sampleCount = stats.sample.length; + const sampleCount = stats.sample.length; stats.minConfidence = stats.mean - (z * stats.deviation) / nSqrt; stats.maxConfidence = stats.mean + (z * stats.deviation) / nSqrt; - stats.text = `${target.name} ${Math.round(stats.mean * 1000)} ms ± ${Math.round( + const confidence = `${Math.round(stats.mean * 1000)} ms ± ${Math.round( stats.deviation * 1000 )} ms [${Math.round(stats.minConfidence * 1000)} ms; ${Math.round( stats.maxConfidence * 1000 )} ms]`; + stats.text = `${target.name} ${confidence}`; - const baseTestName = target.baseTestName; - const allStats = statsByTests.get(baseTestName); + const collectBy = target.collectBy; + const allStats = statsByTests.get(collectBy); + + console.log( + `Done: ${target.name} ${confidence} (${sampleCount} runs sampled)` + ); if (!allStats) { - console.log(String(target)); - statsByTests.set(baseTestName, [stats]); + statsByTests.set(collectBy, [stats]); return; } @@ -373,14 +531,10 @@ suite.on("cycle", event => { const baselineStats = allStats[1]; console.log( - `Benchmark "${baseTestName}" result: ${headStats.text} is ${Math.round( + `Result: ${headStats.text} is ${Math.round( (baselineStats.mean / headStats.mean) * 100 - 100 )}% ${baselineStats.maxConfidence < headStats.minConfidence ? "slower than" : baselineStats.minConfidence > headStats.maxConfidence ? "faster than" : "the same as"} ${baselineStats.text}` ); }); suite.run({ async: true }); - -suite.on("complete", () => { - remove(baselinesPath); -}); diff --git a/test/benchmarkCases/_helpers/create-tree.mjs b/test/benchmarkCases/_helpers/create-tree.mjs new file mode 100644 index 000000000..c3662c57b --- /dev/null +++ b/test/benchmarkCases/_helpers/create-tree.mjs @@ -0,0 +1,103 @@ +import fs from "fs/promises"; + +const avgCode = ` +const str = "we" + "do" + "some" + "ops"; +for(const x of str.split("")) { + if(x.charCodeAt(0) > 40) { + console.log("omg"); + } else { + console.log(Math.random() * 2 + 3 * 2); + } +} + +// Some comment +const value = 9; + +switch(value) { + case true: + break; + case "magic": + throw new Error("Error!"); + case 9: + (function() { + // extra scope + var x = 123; + var y = 456; + var z = x + z * x / y; + x && y && (z = x ? y : x); + }()) +} + +function a() {} +function b() {} +function c() {} +function d() {} +function e() {} +function f() {} +`; + +async function createTree( + folder, + useRequire = false, + count = 50, + async = undefined +) { + await fs.mkdir(folder, { recursive: true }); + + let remaining = count - 1; + + async function make(prefix, count, depth) { + if (count === 0) { + await fs.writeFile( + `${folder}/${prefix}.js`, + useRequire + ? `module.exports = 1;\n${avgCode}` + : `export default 1;\n${avgCode}` + ); + } else { + const list = []; + + for (let i = 0; i < count; i++) { + if (remaining-- <= 0) break; + const isAsync = + typeof async !== "undefined" + ? depth >= async + : depth <= 4 && i >= 3 && i <= 4; + const module = `${prefix}-${i}`; + + if (isAsync) { + list.push( + useRequire + ? `require.ensure([], function() { const module${i} = require(${JSON.stringify(`./${module}.js`)}); });\n` + : `const module${i} = await import(${JSON.stringify(`./${module}.js`)});\n` + ); + list.push(`counter += module${i};\nconsole.log(counter)`); + } else { + list.push( + useRequire + ? `const module${i} = require(${JSON.stringify(`./${module}.js`)});\n` + : `import module${i} from ${JSON.stringify(`./${module}.js`)};\n` + ); + list.push(`counter += module${i};\nconsole.log(counter)`); + } + + await make( + module, + depth > 4 || count > 30 ? 0 : count + depth + i ** 2, + depth + 1 + ); + } + + await fs.writeFile( + `${folder}/${prefix}.js`, + `let counter = 0;\n${list.join( + "\n" + )};\n${useRequire ? `module.exports = counter;\n${avgCode}` : `export default counter;\n${avgCode}`}` + ); + } + } + + await make("module", 2, 0); +} + +export default createTree; diff --git a/test/benchmarkCases/cache-filesystem/index.js b/test/benchmarkCases/cache-filesystem/index.js new file mode 100644 index 000000000..29d87b74b --- /dev/null +++ b/test/benchmarkCases/cache-filesystem/index.js @@ -0,0 +1,2 @@ +import * as mod from "three/src/Three.js"; +export { mod }; diff --git a/test/benchmarkCases/cache-filesystem/webpack.config.js b/test/benchmarkCases/cache-filesystem/webpack.config.js new file mode 100644 index 000000000..9d55f533c --- /dev/null +++ b/test/benchmarkCases/cache-filesystem/webpack.config.js @@ -0,0 +1,7 @@ +/** @type {import("../../../").Configuration} */ +module.exports = { + entry: "./index", + cache: { + type: "filesystem" + } +}; diff --git a/test/benchmarkCases/context-commonjs/index.js b/test/benchmarkCases/context-commonjs/index.js new file mode 100644 index 000000000..b6dfd51fa --- /dev/null +++ b/test/benchmarkCases/context-commonjs/index.js @@ -0,0 +1,6 @@ +async function run() { + const mod = "module.js" + + require(`./generated/${mod}`); +} + diff --git a/test/benchmarkCases/context-commonjs/setup.mjs b/test/benchmarkCases/context-commonjs/setup.mjs new file mode 100644 index 000000000..a59b64808 --- /dev/null +++ b/test/benchmarkCases/context-commonjs/setup.mjs @@ -0,0 +1,11 @@ +import createTree from "../_helpers/create-tree.mjs"; +import { resolve, dirname } from "path"; +import { fileURLToPath } from "url"; +import fs from "fs/promises"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const generated = resolve(__dirname, "./generated"); + +await fs.rm(generated, { recursive: true, force: true }); + +await createTree(generated, true, 25); diff --git a/test/benchmarkCases/many-chunks/webpack.config.js b/test/benchmarkCases/context-commonjs/webpack.config.js similarity index 100% rename from test/benchmarkCases/many-chunks/webpack.config.js rename to test/benchmarkCases/context-commonjs/webpack.config.js diff --git a/test/benchmarkCases/context-esm/index.js b/test/benchmarkCases/context-esm/index.js new file mode 100644 index 000000000..4c150e112 --- /dev/null +++ b/test/benchmarkCases/context-esm/index.js @@ -0,0 +1,5 @@ +async function run() { + const mod = "module.js" + + await import(`./generated/${mod}`); +} diff --git a/test/benchmarkCases/context-esm/setup.mjs b/test/benchmarkCases/context-esm/setup.mjs new file mode 100644 index 000000000..1ce8601cb --- /dev/null +++ b/test/benchmarkCases/context-esm/setup.mjs @@ -0,0 +1,11 @@ +import createTree from "../_helpers/create-tree.mjs"; +import { resolve, dirname } from "path"; +import { fileURLToPath } from "url"; +import fs from "fs/promises"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const generated = resolve(__dirname, "./generated"); + +await fs.rm(generated, { recursive: true, force: true }); + +await createTree(generated, false, 25); diff --git a/test/benchmarkCases/many-modules/webpack.config.js b/test/benchmarkCases/context-esm/webpack.config.js similarity index 100% rename from test/benchmarkCases/many-modules/webpack.config.js rename to test/benchmarkCases/context-esm/webpack.config.js diff --git a/test/benchmarkCases/devtool-eval-source-map/index.js b/test/benchmarkCases/devtool-eval-source-map/index.js new file mode 100644 index 000000000..5650bccde --- /dev/null +++ b/test/benchmarkCases/devtool-eval-source-map/index.js @@ -0,0 +1,2 @@ +import * as mod from "./generated/module.js"; +export { mod }; diff --git a/test/benchmarkCases/devtool-eval-source-map/setup.mjs b/test/benchmarkCases/devtool-eval-source-map/setup.mjs new file mode 100644 index 000000000..fdf3d7256 --- /dev/null +++ b/test/benchmarkCases/devtool-eval-source-map/setup.mjs @@ -0,0 +1,11 @@ +import createTree from "../_helpers/create-tree.mjs"; +import { resolve, dirname } from "path"; +import { fileURLToPath } from "url"; +import fs from "fs/promises"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const generated = resolve(__dirname, "./generated"); + +await fs.rm(generated, { recursive: true, force: true }); + +await createTree(generated); diff --git a/test/benchmarkCases/devtool-eval-source-map/webpack.config.js b/test/benchmarkCases/devtool-eval-source-map/webpack.config.js new file mode 100644 index 000000000..7c2042e3c --- /dev/null +++ b/test/benchmarkCases/devtool-eval-source-map/webpack.config.js @@ -0,0 +1,5 @@ +/** @type {import("../../../").Configuration} */ +module.exports = { + entry: "./index", + devtool: "eval-source-map" +}; diff --git a/test/benchmarkCases/devtool-eval/index.js b/test/benchmarkCases/devtool-eval/index.js new file mode 100644 index 000000000..5650bccde --- /dev/null +++ b/test/benchmarkCases/devtool-eval/index.js @@ -0,0 +1,2 @@ +import * as mod from "./generated/module.js"; +export { mod }; diff --git a/test/benchmarkCases/devtool-eval/setup.mjs b/test/benchmarkCases/devtool-eval/setup.mjs new file mode 100644 index 000000000..fdf3d7256 --- /dev/null +++ b/test/benchmarkCases/devtool-eval/setup.mjs @@ -0,0 +1,11 @@ +import createTree from "../_helpers/create-tree.mjs"; +import { resolve, dirname } from "path"; +import { fileURLToPath } from "url"; +import fs from "fs/promises"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const generated = resolve(__dirname, "./generated"); + +await fs.rm(generated, { recursive: true, force: true }); + +await createTree(generated); diff --git a/test/benchmarkCases/popular-libraries/webpack.config.js b/test/benchmarkCases/devtool-eval/webpack.config.js similarity index 63% rename from test/benchmarkCases/popular-libraries/webpack.config.js rename to test/benchmarkCases/devtool-eval/webpack.config.js index 48485fde0..3f99d3bfc 100644 --- a/test/benchmarkCases/popular-libraries/webpack.config.js +++ b/test/benchmarkCases/devtool-eval/webpack.config.js @@ -1,4 +1,5 @@ /** @type {import("../../../").Configuration} */ module.exports = { - entry: ["react", "react-dom", "lodash"] + entry: "./index", + devtool: "eval" }; diff --git a/test/benchmarkCases/devtool-source-map/a.js b/test/benchmarkCases/devtool-source-map/a.js deleted file mode 100644 index d33ec306d..000000000 --- a/test/benchmarkCases/devtool-source-map/a.js +++ /dev/null @@ -1,10 +0,0 @@ -require("./b?0" + __resourceQuery); -require("./b?1" + __resourceQuery); -require("./b?2" + __resourceQuery); -require("./b?3" + __resourceQuery); -require("./b?4" + __resourceQuery); -require("./b?5" + __resourceQuery); -require("./b?6" + __resourceQuery); -require("./b?7" + __resourceQuery); -require("./b?8" + __resourceQuery); -require("./b?9" + __resourceQuery); diff --git a/test/benchmarkCases/devtool-source-map/b.js b/test/benchmarkCases/devtool-source-map/b.js deleted file mode 100644 index d0d91d3f7..000000000 --- a/test/benchmarkCases/devtool-source-map/b.js +++ /dev/null @@ -1,11 +0,0 @@ -require("./c?0" + __resourceQuery); -require("./c?1" + __resourceQuery); -require("./c?2" + __resourceQuery); -require("./c?3" + __resourceQuery); -require("./c?4" + __resourceQuery); -require("./c?5" + __resourceQuery); -require("./c?6" + __resourceQuery); -require("./c?7" + __resourceQuery); -require("./c?8" + __resourceQuery); -require("./c?9" + __resourceQuery); -require("./a" + __resourceQuery.slice(0, 2)); diff --git a/test/benchmarkCases/devtool-source-map/c.js b/test/benchmarkCases/devtool-source-map/c.js deleted file mode 100644 index 3d17d0002..000000000 --- a/test/benchmarkCases/devtool-source-map/c.js +++ /dev/null @@ -1 +0,0 @@ -// content diff --git a/test/benchmarkCases/devtool-source-map/index.js b/test/benchmarkCases/devtool-source-map/index.js index 68edddd83..5650bccde 100644 --- a/test/benchmarkCases/devtool-source-map/index.js +++ b/test/benchmarkCases/devtool-source-map/index.js @@ -1,10 +1,2 @@ -import "./a?0"; -import "./a?1"; -import "./a?2"; -import "./a?3"; -import "./a?4"; -import "./a?5"; -import "./a?6"; -import "./a?7"; -import "./a?8"; -import "./a?9"; +import * as mod from "./generated/module.js"; +export { mod }; diff --git a/test/benchmarkCases/devtool-source-map/setup.mjs b/test/benchmarkCases/devtool-source-map/setup.mjs new file mode 100644 index 000000000..fdf3d7256 --- /dev/null +++ b/test/benchmarkCases/devtool-source-map/setup.mjs @@ -0,0 +1,11 @@ +import createTree from "../_helpers/create-tree.mjs"; +import { resolve, dirname } from "path"; +import { fileURLToPath } from "url"; +import fs from "fs/promises"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const generated = resolve(__dirname, "./generated"); + +await fs.rm(generated, { recursive: true, force: true }); + +await createTree(generated); diff --git a/test/benchmarkCases/future-defaults/index.js b/test/benchmarkCases/future-defaults/index.js new file mode 100644 index 000000000..c15055d3f --- /dev/null +++ b/test/benchmarkCases/future-defaults/index.js @@ -0,0 +1,2 @@ +import * as mod from "./generated/module.js"; +export { mod } diff --git a/test/benchmarkCases/future-defaults/setup.mjs b/test/benchmarkCases/future-defaults/setup.mjs new file mode 100644 index 000000000..699fc153f --- /dev/null +++ b/test/benchmarkCases/future-defaults/setup.mjs @@ -0,0 +1,11 @@ +import createTree from "../_helpers/create-tree.mjs"; +import { resolve, dirname } from "path"; +import { fileURLToPath } from "url"; +import fs from "fs/promises"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const generated = resolve(__dirname, "./generated"); + +await fs.rm(generated, { recursive: true, force: true }); + +await createTree(generated, false, 75); diff --git a/test/benchmarkCases/future-defaults/webpack.config.js b/test/benchmarkCases/future-defaults/webpack.config.js new file mode 100644 index 000000000..77b0a2329 --- /dev/null +++ b/test/benchmarkCases/future-defaults/webpack.config.js @@ -0,0 +1,7 @@ +/** @type {import("../../../").Configuration} */ +module.exports = { + entry: "./index", + experiments: { + futureDefaults: true + } +}; diff --git a/test/benchmarkCases/many-chunks-commonjs/index.js b/test/benchmarkCases/many-chunks-commonjs/index.js new file mode 100644 index 000000000..fa37ca1f3 --- /dev/null +++ b/test/benchmarkCases/many-chunks-commonjs/index.js @@ -0,0 +1,2 @@ +const result = require("./generated/module.js"); +module.exports = result; diff --git a/test/benchmarkCases/many-chunks-commonjs/setup.mjs b/test/benchmarkCases/many-chunks-commonjs/setup.mjs new file mode 100644 index 000000000..efad0e2b8 --- /dev/null +++ b/test/benchmarkCases/many-chunks-commonjs/setup.mjs @@ -0,0 +1,11 @@ +import createTree from "../_helpers/create-tree.mjs"; +import { resolve, dirname } from "path"; +import { fileURLToPath } from "url"; +import fs from "fs/promises"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const generated = resolve(__dirname, "./generated"); + +await fs.rm(generated, { recursive: true, force: true }); + +await createTree(generated, true, 50, 0); diff --git a/test/benchmarkCases/many-chunks-commonjs/webpack.config.js b/test/benchmarkCases/many-chunks-commonjs/webpack.config.js new file mode 100644 index 000000000..4c111be6a --- /dev/null +++ b/test/benchmarkCases/many-chunks-commonjs/webpack.config.js @@ -0,0 +1,4 @@ +/** @type {import("../../../").Configuration} */ +module.exports = { + entry: "./index" +}; diff --git a/test/benchmarkCases/many-chunks-esm/index.js b/test/benchmarkCases/many-chunks-esm/index.js new file mode 100644 index 000000000..5650bccde --- /dev/null +++ b/test/benchmarkCases/many-chunks-esm/index.js @@ -0,0 +1,2 @@ +import * as mod from "./generated/module.js"; +export { mod }; diff --git a/test/benchmarkCases/many-chunks-esm/setup.mjs b/test/benchmarkCases/many-chunks-esm/setup.mjs new file mode 100644 index 000000000..2e2f46da4 --- /dev/null +++ b/test/benchmarkCases/many-chunks-esm/setup.mjs @@ -0,0 +1,11 @@ +import createTree from "../_helpers/create-tree.mjs"; +import { resolve, dirname } from "path"; +import { fileURLToPath } from "url"; +import fs from "fs/promises"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const generated = resolve(__dirname, "./generated"); + +await fs.rm(generated, { recursive: true, force: true }); + +await createTree(generated, false, 50, 0); diff --git a/test/benchmarkCases/many-chunks-esm/webpack.config.js b/test/benchmarkCases/many-chunks-esm/webpack.config.js new file mode 100644 index 000000000..4c111be6a --- /dev/null +++ b/test/benchmarkCases/many-chunks-esm/webpack.config.js @@ -0,0 +1,4 @@ +/** @type {import("../../../").Configuration} */ +module.exports = { + entry: "./index" +}; diff --git a/test/benchmarkCases/many-chunks/a.js b/test/benchmarkCases/many-chunks/a.js deleted file mode 100644 index 410cf0a69..000000000 --- a/test/benchmarkCases/many-chunks/a.js +++ /dev/null @@ -1,10 +0,0 @@ -import("./b?0" + __resourceQuery); -import("./b?1" + __resourceQuery); -import("./b?2" + __resourceQuery); -import("./b?3" + __resourceQuery); -import("./b?4" + __resourceQuery); -import("./b?5" + __resourceQuery); -import("./b?6" + __resourceQuery); -import("./b?7" + __resourceQuery); -import("./b?8" + __resourceQuery); -import("./b?9" + __resourceQuery); diff --git a/test/benchmarkCases/many-chunks/b.js b/test/benchmarkCases/many-chunks/b.js deleted file mode 100644 index 3d3fd298e..000000000 --- a/test/benchmarkCases/many-chunks/b.js +++ /dev/null @@ -1,6 +0,0 @@ -import("./c?0" + __resourceQuery); -import("./c?1" + __resourceQuery); -import("./c?2" + __resourceQuery); -import("./c?3" + __resourceQuery); -import("./c?4" + __resourceQuery); -import("./a" + __resourceQuery.slice(0, 2)); diff --git a/test/benchmarkCases/many-chunks/c.js b/test/benchmarkCases/many-chunks/c.js deleted file mode 100644 index 3d17d0002..000000000 --- a/test/benchmarkCases/many-chunks/c.js +++ /dev/null @@ -1 +0,0 @@ -// content diff --git a/test/benchmarkCases/many-chunks/index.js b/test/benchmarkCases/many-chunks/index.js deleted file mode 100644 index 4ab3926df..000000000 --- a/test/benchmarkCases/many-chunks/index.js +++ /dev/null @@ -1,10 +0,0 @@ -import("./a?0"); -import("./a?1"); -import("./a?2"); -import("./a?3"); -import("./a?4"); -import("./a?5"); -import("./a?6"); -import("./a?7"); -import("./a?8"); -import("./a?9"); diff --git a/test/benchmarkCases/many-modules-commonjs/index.js b/test/benchmarkCases/many-modules-commonjs/index.js new file mode 100644 index 000000000..fa37ca1f3 --- /dev/null +++ b/test/benchmarkCases/many-modules-commonjs/index.js @@ -0,0 +1,2 @@ +const result = require("./generated/module.js"); +module.exports = result; diff --git a/test/benchmarkCases/many-modules-commonjs/setup.mjs b/test/benchmarkCases/many-modules-commonjs/setup.mjs new file mode 100644 index 000000000..345612b20 --- /dev/null +++ b/test/benchmarkCases/many-modules-commonjs/setup.mjs @@ -0,0 +1,11 @@ +import createTree from "../_helpers/create-tree.mjs"; +import { resolve, dirname } from "path"; +import { fileURLToPath } from "url"; +import fs from "fs/promises"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const generated = resolve(__dirname, "./generated"); + +await fs.rm(generated, { recursive: true, force: true }); + +await createTree(generated, true, 75); diff --git a/test/benchmarkCases/many-modules-commonjs/webpack.config.js b/test/benchmarkCases/many-modules-commonjs/webpack.config.js new file mode 100644 index 000000000..4c111be6a --- /dev/null +++ b/test/benchmarkCases/many-modules-commonjs/webpack.config.js @@ -0,0 +1,4 @@ +/** @type {import("../../../").Configuration} */ +module.exports = { + entry: "./index" +}; diff --git a/test/benchmarkCases/many-modules-esm/index.js b/test/benchmarkCases/many-modules-esm/index.js new file mode 100644 index 000000000..5650bccde --- /dev/null +++ b/test/benchmarkCases/many-modules-esm/index.js @@ -0,0 +1,2 @@ +import * as mod from "./generated/module.js"; +export { mod }; diff --git a/test/benchmarkCases/many-modules-esm/setup.mjs b/test/benchmarkCases/many-modules-esm/setup.mjs new file mode 100644 index 000000000..699fc153f --- /dev/null +++ b/test/benchmarkCases/many-modules-esm/setup.mjs @@ -0,0 +1,11 @@ +import createTree from "../_helpers/create-tree.mjs"; +import { resolve, dirname } from "path"; +import { fileURLToPath } from "url"; +import fs from "fs/promises"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const generated = resolve(__dirname, "./generated"); + +await fs.rm(generated, { recursive: true, force: true }); + +await createTree(generated, false, 75); diff --git a/test/benchmarkCases/many-modules-esm/webpack.config.js b/test/benchmarkCases/many-modules-esm/webpack.config.js new file mode 100644 index 000000000..4c111be6a --- /dev/null +++ b/test/benchmarkCases/many-modules-esm/webpack.config.js @@ -0,0 +1,4 @@ +/** @type {import("../../../").Configuration} */ +module.exports = { + entry: "./index" +}; diff --git a/test/benchmarkCases/many-modules/a.js b/test/benchmarkCases/many-modules/a.js deleted file mode 100644 index d33ec306d..000000000 --- a/test/benchmarkCases/many-modules/a.js +++ /dev/null @@ -1,10 +0,0 @@ -require("./b?0" + __resourceQuery); -require("./b?1" + __resourceQuery); -require("./b?2" + __resourceQuery); -require("./b?3" + __resourceQuery); -require("./b?4" + __resourceQuery); -require("./b?5" + __resourceQuery); -require("./b?6" + __resourceQuery); -require("./b?7" + __resourceQuery); -require("./b?8" + __resourceQuery); -require("./b?9" + __resourceQuery); diff --git a/test/benchmarkCases/many-modules/b.js b/test/benchmarkCases/many-modules/b.js deleted file mode 100644 index d0d91d3f7..000000000 --- a/test/benchmarkCases/many-modules/b.js +++ /dev/null @@ -1,11 +0,0 @@ -require("./c?0" + __resourceQuery); -require("./c?1" + __resourceQuery); -require("./c?2" + __resourceQuery); -require("./c?3" + __resourceQuery); -require("./c?4" + __resourceQuery); -require("./c?5" + __resourceQuery); -require("./c?6" + __resourceQuery); -require("./c?7" + __resourceQuery); -require("./c?8" + __resourceQuery); -require("./c?9" + __resourceQuery); -require("./a" + __resourceQuery.slice(0, 2)); diff --git a/test/benchmarkCases/many-modules/c.js b/test/benchmarkCases/many-modules/c.js deleted file mode 100644 index 3d17d0002..000000000 --- a/test/benchmarkCases/many-modules/c.js +++ /dev/null @@ -1 +0,0 @@ -// content diff --git a/test/benchmarkCases/many-modules/index.js b/test/benchmarkCases/many-modules/index.js deleted file mode 100644 index 68edddd83..000000000 --- a/test/benchmarkCases/many-modules/index.js +++ /dev/null @@ -1,10 +0,0 @@ -import "./a?0"; -import "./a?1"; -import "./a?2"; -import "./a?3"; -import "./a?4"; -import "./a?5"; -import "./a?6"; -import "./a?7"; -import "./a?8"; -import "./a?9"; diff --git a/test/benchmarkCases/minimal/index.js b/test/benchmarkCases/minimal/index.js new file mode 100644 index 000000000..b179ee953 --- /dev/null +++ b/test/benchmarkCases/minimal/index.js @@ -0,0 +1 @@ +console.log("Hello world"); diff --git a/test/benchmarkCases/minimal/webpack.config.js b/test/benchmarkCases/minimal/webpack.config.js new file mode 100644 index 000000000..4c111be6a --- /dev/null +++ b/test/benchmarkCases/minimal/webpack.config.js @@ -0,0 +1,4 @@ +/** @type {import("../../../").Configuration} */ +module.exports = { + entry: "./index" +}; diff --git a/test/benchmarkCases/popular-libraries-long/index.js b/test/benchmarkCases/popular-libraries-long/index.js new file mode 100644 index 000000000..af615f6fc --- /dev/null +++ b/test/benchmarkCases/popular-libraries-long/index.js @@ -0,0 +1,6 @@ +import * as mod1 from "react"; +export { mod1 }; +import * as mod2 from "react-dom"; +export { mod2 }; +import * as mod3 from "lodash"; +export { mod3 }; diff --git a/test/benchmarkCases/popular-libraries-long/webpack.config.js b/test/benchmarkCases/popular-libraries-long/webpack.config.js new file mode 100644 index 000000000..4c111be6a --- /dev/null +++ b/test/benchmarkCases/popular-libraries-long/webpack.config.js @@ -0,0 +1,4 @@ +/** @type {import("../../../").Configuration} */ +module.exports = { + entry: "./index" +}; diff --git a/test/benchmarkCases/three-long/index.js b/test/benchmarkCases/three-long/index.js new file mode 100644 index 000000000..432347928 --- /dev/null +++ b/test/benchmarkCases/three-long/index.js @@ -0,0 +1,2 @@ +import * as copy from "three/src/Three.js"; +export { copy }; diff --git a/test/benchmarkCases/three-long/webpack.config.js b/test/benchmarkCases/three-long/webpack.config.js new file mode 100644 index 000000000..4c111be6a --- /dev/null +++ b/test/benchmarkCases/three-long/webpack.config.js @@ -0,0 +1,4 @@ +/** @type {import("../../../").Configuration} */ +module.exports = { + entry: "./index" +}; diff --git a/test/benchmarkCases/typescript-long/index.js b/test/benchmarkCases/typescript-long/index.js new file mode 100644 index 000000000..7948b6017 --- /dev/null +++ b/test/benchmarkCases/typescript-long/index.js @@ -0,0 +1,2 @@ +import * as mod from "typescript"; +export { mod }; diff --git a/test/benchmarkCases/typescript-long/webpack.config.js b/test/benchmarkCases/typescript-long/webpack.config.js new file mode 100644 index 000000000..9c5de9f77 --- /dev/null +++ b/test/benchmarkCases/typescript-long/webpack.config.js @@ -0,0 +1,11 @@ +/** @type {import("../../../").Configuration} */ +module.exports = { + entry: "./index", + target: "node", + optimization: { + avoidEntryIife: false, + // terser is very slow on typescript code, need to investigate + minimize: false + }, + ignoreWarnings: [/Critical dependency/] +}; diff --git a/yarn.lock b/yarn.lock index 133ba0522..5a616fb3b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6334,6 +6334,11 @@ thingies@^1.20.0: resolved "https://registry.yarnpkg.com/thingies/-/thingies-1.21.0.tgz#e80fbe58fd6fdaaab8fad9b67bd0a5c943c445c1" integrity sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g== +three@^0.176.0: + version "0.176.0" + resolved "https://registry.yarnpkg.com/three/-/three-0.176.0.tgz#a30c1974e46db5745e4f96dd9ee2028d71e16ecf" + integrity sha512-PWRKYWQo23ojf9oZSlRGH8K09q7nRSWx6LY/HF/UUrMdYgN9i1e2OwJYHoQjwc6HF/4lvvYLC5YC1X8UJL2ZpA== + timers-ext@^0.1.7: version "0.1.8" resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.8.tgz#b4e442f10b7624a29dd2aa42c295e257150cf16c"