From f6117bb3285c4aaf0d9003b2cca73d8a60150d8b Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Tue, 19 Nov 2024 18:06:32 +0000 Subject: [PATCH] chore: add ssr benchmark suite (#14361) * chore: add ssr benchmark suite * lint * Update benchmarking/run.js Co-authored-by: Rich Harris --------- Co-authored-by: Rich Harris --- benchmarking/.gitignore | 1 + .../reactivity/index.js} | 25 +++++------ .../{ => reactivity}/kairo/kairo_avoidable.js | 4 +- .../{ => reactivity}/kairo/kairo_broad.js | 4 +- .../{ => reactivity}/kairo/kairo_deep.js | 4 +- .../{ => reactivity}/kairo/kairo_diamond.js | 4 +- .../{ => reactivity}/kairo/kairo_mux.js | 4 +- .../{ => reactivity}/kairo/kairo_repeated.js | 4 +- .../{ => reactivity}/kairo/kairo_triangle.js | 4 +- .../{ => reactivity}/kairo/kairo_unstable.js | 4 +- .../benchmarks/{ => reactivity}/kairo/util.js | 0 .../benchmarks/{ => reactivity}/mol_bench.js | 4 +- .../benchmarks/{ => reactivity}/sbench.js | 4 +- benchmarking/benchmarks/ssr/index.js | 3 ++ .../benchmarks/ssr/wrapper/App.svelte | 31 ++++++++++++++ .../benchmarks/ssr/wrapper/wrapper_bench.js | 36 ++++++++++++++++ benchmarking/run.js | 41 +++++++++++++++---- benchmarking/utils.js | 21 ++++++++++ 18 files changed, 155 insertions(+), 43 deletions(-) create mode 100644 benchmarking/.gitignore rename benchmarking/{benchmarks.js => benchmarks/reactivity/index.js} (63%) rename benchmarking/benchmarks/{ => reactivity}/kairo/kairo_avoidable.js (93%) rename benchmarking/benchmarks/{ => reactivity}/kairo/kairo_broad.js (92%) rename benchmarking/benchmarks/{ => reactivity}/kairo/kairo_deep.js (92%) rename benchmarking/benchmarks/{ => reactivity}/kairo/kairo_diamond.js (92%) rename benchmarking/benchmarks/{ => reactivity}/kairo/kairo_mux.js (93%) rename benchmarking/benchmarks/{ => reactivity}/kairo/kairo_repeated.js (92%) rename benchmarking/benchmarks/{ => reactivity}/kairo/kairo_triangle.js (93%) rename benchmarking/benchmarks/{ => reactivity}/kairo/kairo_unstable.js (92%) rename benchmarking/benchmarks/{ => reactivity}/kairo/util.js (100%) rename benchmarking/benchmarks/{ => reactivity}/mol_bench.js (95%) rename benchmarking/benchmarks/{ => reactivity}/sbench.js (98%) create mode 100644 benchmarking/benchmarks/ssr/index.js create mode 100644 benchmarking/benchmarks/ssr/wrapper/App.svelte create mode 100644 benchmarking/benchmarks/ssr/wrapper/wrapper_bench.js diff --git a/benchmarking/.gitignore b/benchmarking/.gitignore new file mode 100644 index 0000000000..53752db253 --- /dev/null +++ b/benchmarking/.gitignore @@ -0,0 +1 @@ +output diff --git a/benchmarking/benchmarks.js b/benchmarking/benchmarks/reactivity/index.js similarity index 63% rename from benchmarking/benchmarks.js rename to benchmarking/benchmarks/reactivity/index.js index 795ac3e09e..58b3f5cb29 100644 --- a/benchmarking/benchmarks.js +++ b/benchmarking/benchmarks/reactivity/index.js @@ -1,15 +1,12 @@ -import { - kairo_avoidable_owned, - kairo_avoidable_unowned -} from './benchmarks/kairo/kairo_avoidable.js'; -import { kairo_broad_owned, kairo_broad_unowned } from './benchmarks/kairo/kairo_broad.js'; -import { kairo_deep_owned, kairo_deep_unowned } from './benchmarks/kairo/kairo_deep.js'; -import { kairo_diamond_owned, kairo_diamond_unowned } from './benchmarks/kairo/kairo_diamond.js'; -import { kairo_mux_unowned, kairo_mux_owned } from './benchmarks/kairo/kairo_mux.js'; -import { kairo_repeated_unowned, kairo_repeated_owned } from './benchmarks/kairo/kairo_repeated.js'; -import { kairo_triangle_owned, kairo_triangle_unowned } from './benchmarks/kairo/kairo_triangle.js'; -import { kairo_unstable_owned, kairo_unstable_unowned } from './benchmarks/kairo/kairo_unstable.js'; -import { mol_bench_owned, mol_bench_unowned } from './benchmarks/mol_bench.js'; +import { kairo_avoidable_owned, kairo_avoidable_unowned } from './kairo/kairo_avoidable.js'; +import { kairo_broad_owned, kairo_broad_unowned } from './kairo/kairo_broad.js'; +import { kairo_deep_owned, kairo_deep_unowned } from './kairo/kairo_deep.js'; +import { kairo_diamond_owned, kairo_diamond_unowned } from './kairo/kairo_diamond.js'; +import { kairo_mux_unowned, kairo_mux_owned } from './kairo/kairo_mux.js'; +import { kairo_repeated_unowned, kairo_repeated_owned } from './kairo/kairo_repeated.js'; +import { kairo_triangle_owned, kairo_triangle_unowned } from './kairo/kairo_triangle.js'; +import { kairo_unstable_owned, kairo_unstable_unowned } from './kairo/kairo_unstable.js'; +import { mol_bench_owned, mol_bench_unowned } from './mol_bench.js'; import { sbench_create_0to1, sbench_create_1000to1, @@ -21,12 +18,12 @@ import { sbench_create_2to1, sbench_create_4to1, sbench_create_signals -} from './benchmarks/sbench.js'; +} from './sbench.js'; // This benchmark has been adapted from the js-reactivity-benchmark (https://github.com/milomg/js-reactivity-benchmark) // Not all tests are the same, and many parts have been tweaked to capture different data. -export const benchmarks = [ +export const reactivity_benchmarks = [ sbench_create_signals, sbench_create_0to1, sbench_create_1to1, diff --git a/benchmarking/benchmarks/kairo/kairo_avoidable.js b/benchmarking/benchmarks/reactivity/kairo/kairo_avoidable.js similarity index 93% rename from benchmarking/benchmarks/kairo/kairo_avoidable.js rename to benchmarking/benchmarks/reactivity/kairo/kairo_avoidable.js index 76bd4c72e3..1237547ebe 100644 --- a/benchmarking/benchmarks/kairo/kairo_avoidable.js +++ b/benchmarking/benchmarks/reactivity/kairo/kairo_avoidable.js @@ -1,5 +1,5 @@ -import { assert, fastest_test } from '../../utils.js'; -import * as $ from '../../../packages/svelte/src/internal/client/index.js'; +import { assert, fastest_test } from '../../../utils.js'; +import * as $ from 'svelte/internal/client'; import { busy } from './util.js'; function setup() { diff --git a/benchmarking/benchmarks/kairo/kairo_broad.js b/benchmarking/benchmarks/reactivity/kairo/kairo_broad.js similarity index 92% rename from benchmarking/benchmarks/kairo/kairo_broad.js rename to benchmarking/benchmarks/reactivity/kairo/kairo_broad.js index d7b37d153c..8148a743ea 100644 --- a/benchmarking/benchmarks/kairo/kairo_broad.js +++ b/benchmarking/benchmarks/reactivity/kairo/kairo_broad.js @@ -1,5 +1,5 @@ -import { assert, fastest_test } from '../../utils.js'; -import * as $ from '../../../packages/svelte/src/internal/client/index.js'; +import { assert, fastest_test } from '../../../utils.js'; +import * as $ from 'svelte/internal/client'; function setup() { let head = $.state(0); diff --git a/benchmarking/benchmarks/kairo/kairo_deep.js b/benchmarking/benchmarks/reactivity/kairo/kairo_deep.js similarity index 92% rename from benchmarking/benchmarks/kairo/kairo_deep.js rename to benchmarking/benchmarks/reactivity/kairo/kairo_deep.js index cc29940738..806042cc72 100644 --- a/benchmarking/benchmarks/kairo/kairo_deep.js +++ b/benchmarking/benchmarks/reactivity/kairo/kairo_deep.js @@ -1,5 +1,5 @@ -import { assert, fastest_test } from '../../utils.js'; -import * as $ from '../../../packages/svelte/src/internal/client/index.js'; +import { assert, fastest_test } from '../../../utils.js'; +import * as $ from 'svelte/internal/client'; let len = 50; const iter = 50; diff --git a/benchmarking/benchmarks/kairo/kairo_diamond.js b/benchmarking/benchmarks/reactivity/kairo/kairo_diamond.js similarity index 92% rename from benchmarking/benchmarks/kairo/kairo_diamond.js rename to benchmarking/benchmarks/reactivity/kairo/kairo_diamond.js index 0492454966..deb9482de9 100644 --- a/benchmarking/benchmarks/kairo/kairo_diamond.js +++ b/benchmarking/benchmarks/reactivity/kairo/kairo_diamond.js @@ -1,5 +1,5 @@ -import { assert, fastest_test } from '../../utils.js'; -import * as $ from '../../../packages/svelte/src/internal/client/index.js'; +import { assert, fastest_test } from '../../../utils.js'; +import * as $ from 'svelte/internal/client'; let width = 5; diff --git a/benchmarking/benchmarks/kairo/kairo_mux.js b/benchmarking/benchmarks/reactivity/kairo/kairo_mux.js similarity index 93% rename from benchmarking/benchmarks/kairo/kairo_mux.js rename to benchmarking/benchmarks/reactivity/kairo/kairo_mux.js index 769e14c43e..8eafacc9eb 100644 --- a/benchmarking/benchmarks/kairo/kairo_mux.js +++ b/benchmarking/benchmarks/reactivity/kairo/kairo_mux.js @@ -1,5 +1,5 @@ -import { assert, fastest_test } from '../../utils.js'; -import * as $ from '../../../packages/svelte/src/internal/client/index.js'; +import { assert, fastest_test } from '../../../utils.js'; +import * as $ from 'svelte/internal/client'; function setup() { let heads = new Array(100).fill(null).map((_) => $.state(0)); diff --git a/benchmarking/benchmarks/kairo/kairo_repeated.js b/benchmarking/benchmarks/reactivity/kairo/kairo_repeated.js similarity index 92% rename from benchmarking/benchmarks/kairo/kairo_repeated.js rename to benchmarking/benchmarks/reactivity/kairo/kairo_repeated.js index 2416f89dfd..2bddf879c9 100644 --- a/benchmarking/benchmarks/kairo/kairo_repeated.js +++ b/benchmarking/benchmarks/reactivity/kairo/kairo_repeated.js @@ -1,5 +1,5 @@ -import { assert, fastest_test } from '../../utils.js'; -import * as $ from '../../../packages/svelte/src/internal/client/index.js'; +import { assert, fastest_test } from '../../../utils.js'; +import * as $ from 'svelte/internal/client'; let size = 30; diff --git a/benchmarking/benchmarks/kairo/kairo_triangle.js b/benchmarking/benchmarks/reactivity/kairo/kairo_triangle.js similarity index 93% rename from benchmarking/benchmarks/kairo/kairo_triangle.js rename to benchmarking/benchmarks/reactivity/kairo/kairo_triangle.js index ee9311c96a..9d99b7815b 100644 --- a/benchmarking/benchmarks/kairo/kairo_triangle.js +++ b/benchmarking/benchmarks/reactivity/kairo/kairo_triangle.js @@ -1,5 +1,5 @@ -import { assert, fastest_test } from '../../utils.js'; -import * as $ from '../../../packages/svelte/src/internal/client/index.js'; +import { assert, fastest_test } from '../../../utils.js'; +import * as $ from 'svelte/internal/client'; let width = 10; diff --git a/benchmarking/benchmarks/kairo/kairo_unstable.js b/benchmarking/benchmarks/reactivity/kairo/kairo_unstable.js similarity index 92% rename from benchmarking/benchmarks/kairo/kairo_unstable.js rename to benchmarking/benchmarks/reactivity/kairo/kairo_unstable.js index b05fc0745a..c30c007561 100644 --- a/benchmarking/benchmarks/kairo/kairo_unstable.js +++ b/benchmarking/benchmarks/reactivity/kairo/kairo_unstable.js @@ -1,5 +1,5 @@ -import { assert, fastest_test } from '../../utils.js'; -import * as $ from '../../../packages/svelte/src/internal/client/index.js'; +import { assert, fastest_test } from '../../../utils.js'; +import * as $ from 'svelte/internal/client'; function setup() { let head = $.state(0); diff --git a/benchmarking/benchmarks/kairo/util.js b/benchmarking/benchmarks/reactivity/kairo/util.js similarity index 100% rename from benchmarking/benchmarks/kairo/util.js rename to benchmarking/benchmarks/reactivity/kairo/util.js diff --git a/benchmarking/benchmarks/mol_bench.js b/benchmarking/benchmarks/reactivity/mol_bench.js similarity index 95% rename from benchmarking/benchmarks/mol_bench.js rename to benchmarking/benchmarks/reactivity/mol_bench.js index a962f5e148..c9f492f619 100644 --- a/benchmarking/benchmarks/mol_bench.js +++ b/benchmarking/benchmarks/reactivity/mol_bench.js @@ -1,5 +1,5 @@ -import { assert, fastest_test } from '../utils.js'; -import * as $ from '../../packages/svelte/src/internal/client/index.js'; +import { assert, fastest_test } from '../../utils.js'; +import * as $ from 'svelte/internal/client'; /** * @param {number} n diff --git a/benchmarking/benchmarks/sbench.js b/benchmarking/benchmarks/reactivity/sbench.js similarity index 98% rename from benchmarking/benchmarks/sbench.js rename to benchmarking/benchmarks/reactivity/sbench.js index f390d84463..ddeaef2514 100644 --- a/benchmarking/benchmarks/sbench.js +++ b/benchmarking/benchmarks/reactivity/sbench.js @@ -1,5 +1,5 @@ -import { fastest_test } from '../utils.js'; -import * as $ from '../../packages/svelte/src/internal/client/index.js'; +import { fastest_test } from '../../utils.js'; +import * as $ from '../../../packages/svelte/src/internal/client/index.js'; const COUNT = 1e5; diff --git a/benchmarking/benchmarks/ssr/index.js b/benchmarking/benchmarks/ssr/index.js new file mode 100644 index 0000000000..667137d1ed --- /dev/null +++ b/benchmarking/benchmarks/ssr/index.js @@ -0,0 +1,3 @@ +import { wrapper_bench } from './wrapper/wrapper_bench.js'; + +export const ssr_benchmarks = [wrapper_bench]; diff --git a/benchmarking/benchmarks/ssr/wrapper/App.svelte b/benchmarking/benchmarks/ssr/wrapper/App.svelte new file mode 100644 index 0000000000..93f031f2bc --- /dev/null +++ b/benchmarking/benchmarks/ssr/wrapper/App.svelte @@ -0,0 +1,31 @@ + + +
+ {#each tiles as { x, y }} +
+ {/each} +
diff --git a/benchmarking/benchmarks/ssr/wrapper/wrapper_bench.js b/benchmarking/benchmarks/ssr/wrapper/wrapper_bench.js new file mode 100644 index 0000000000..ba0457b80e --- /dev/null +++ b/benchmarking/benchmarks/ssr/wrapper/wrapper_bench.js @@ -0,0 +1,36 @@ +import { render } from 'svelte/server'; +import { fastest_test, read_file, write } from '../../../utils.js'; +import { compile } from 'svelte/compiler'; + +const dir = `${process.cwd()}/benchmarking/benchmarks/ssr/wrapper`; + +async function compile_svelte() { + const output = compile(read_file(`${dir}/App.svelte`), { + generate: 'server' + }); + write(`${dir}/output/App.js`, output.js.code); + + const module = await import(`${dir}/output/App.js`); + + return module.default; +} + +export async function wrapper_bench() { + const App = await compile_svelte(); + // Do 3 loops to warm up JIT + for (let i = 0; i < 3; i++) { + render(App); + } + + const { timing } = await fastest_test(10, () => { + for (let i = 0; i < 100; i++) { + render(App); + } + }); + + return { + benchmark: 'wrapper_bench', + time: timing.time.toFixed(2), + gc_time: timing.gc_time.toFixed(2) + }; +} diff --git a/benchmarking/run.js b/benchmarking/run.js index 35a6ac307f..bd96b9c2dc 100644 --- a/benchmarking/run.js +++ b/benchmarking/run.js @@ -1,30 +1,53 @@ import * as $ from '../packages/svelte/src/internal/client/index.js'; -import { benchmarks } from './benchmarks.js'; +import { reactivity_benchmarks } from './benchmarks/reactivity/index.js'; +import { ssr_benchmarks } from './benchmarks/ssr/index.js'; let total_time = 0; let total_gc_time = 0; +const suites = [ + { benchmarks: reactivity_benchmarks, name: 'reactivity benchmarks' }, + { benchmarks: ssr_benchmarks, name: 'server-side rendering benchmarks' } +]; + // eslint-disable-next-line no-console -console.log('-- Benchmarking Started --'); +console.log('\x1b[1m', '-- Benchmarking Started --', '\x1b[0m'); $.push({}, true); try { - for (const benchmark of benchmarks) { - const results = await benchmark(); + for (const { benchmarks, name } of suites) { + let suite_time = 0; + let suite_gc_time = 0; + // eslint-disable-next-line no-console + console.log(`\nRunning ${name}...\n`); + + for (const benchmark of benchmarks) { + const results = await benchmark(); + // eslint-disable-next-line no-console + console.log(results); + total_time += Number(results.time); + total_gc_time += Number(results.gc_time); + suite_time += Number(results.time); + suite_gc_time += Number(results.gc_time); + } + + console.log(`\nFinished ${name}.\n`); + // eslint-disable-next-line no-console - console.log(results); - total_time += Number(results.time); - total_gc_time += Number(results.gc_time); + console.log({ + suite_time: suite_time.toFixed(2), + suite_gc_time: suite_gc_time.toFixed(2) + }); } } catch (e) { // eslint-disable-next-line no-console - console.error('-- Benchmarking Failed --'); + console.log('\x1b[1m', '\n-- Benchmarking Failed --\n', '\x1b[0m'); // eslint-disable-next-line no-console console.error(e); process.exit(1); } $.pop(); // eslint-disable-next-line no-console -console.log('-- Benchmarking Complete --'); +console.log('\x1b[1m', '\n-- Benchmarking Complete --\n', '\x1b[0m'); // eslint-disable-next-line no-console console.log({ total_time: total_time.toFixed(2), diff --git a/benchmarking/utils.js b/benchmarking/utils.js index db2fa753ee..684d2ee02b 100644 --- a/benchmarking/utils.js +++ b/benchmarking/utils.js @@ -1,5 +1,7 @@ import { performance, PerformanceObserver } from 'node:perf_hooks'; import v8 from 'v8-natives'; +import * as fs from 'node:fs'; +import * as path from 'node:path'; // Credit to https://github.com/milomg/js-reactivity-benchmark for the logic for timing + GC tracking. @@ -96,3 +98,22 @@ export function assert(a) { throw new Error('Assertion failed'); } } + +/** + * @param {string} file + */ +export function read_file(file) { + return fs.readFileSync(file, 'utf-8').replace(/\r\n/g, '\n'); +} + +/** + * @param {string} file + * @param {string} contents + */ +export function write(file, contents) { + try { + fs.mkdirSync(path.dirname(file), { recursive: true }); + } catch {} + + fs.writeFileSync(file, contents); +}