chore: Add benchmarks for i18n vs vanilla usage (#2372)

This commit is contained in:
Aaron
2026-05-14 06:41:42 -07:00
committed by GitHub
parent dbbe14ddd6
commit 3cb894c4e5
8 changed files with 179 additions and 2 deletions
Generated
+4 -1
View File
@@ -110,6 +110,7 @@
"@types/node": "catalog:",
"oxlint": "catalog:",
"publint": "catalog:",
"tinybench": "^6.0.1",
"tsdown": "catalog:",
"typescript": "catalog:",
"vitest": "catalog:",
@@ -2304,7 +2305,7 @@
"through": ["through@2.3.8", "", {}, "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="],
"tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="],
"tinybench": ["tinybench@6.0.1", "", {}, "sha512-cMdWsxmysdg8mNWf1pujiWl3TW0cU6m8QuNw55QlnP3I6N96Grb0wnu5N0syHIu3LbiVZCNqlfWzWDq84HZphA=="],
"tinyexec": ["tinyexec@1.1.1", "", {}, "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg=="],
@@ -2782,6 +2783,8 @@
"vitest/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
"vitest/tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="],
"vue/@vue/shared": ["@vue/shared@3.5.34", "", {}, "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA=="],
"widest-line/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
+11
View File
@@ -0,0 +1,11 @@
# I18n Benchmarks
These benchmarks must be ran in an actual browser extension environment.
To run them, run `bench/run.ts` and load the `bench/` directory into a browser as an extension. Or just:
```sh
bun --cwd packages/i18n bench
```
Benchmarks are defined in `bench/background.ts`. Add or edit them there.
@@ -0,0 +1,17 @@
{
"simple": {
"message": "Just plain text"
},
"substitution": {
"message": "Includes one substitution: $1"
},
"singular": {
"message": "There is $1 item"
},
"plural": {
"message": "There are $1 items"
},
"wxtPlural": {
"message": "There is $1 item | There are $1 items"
}
}
+85
View File
@@ -0,0 +1,85 @@
import { Bench } from 'tinybench';
import { createI18n } from '../src';
declare const chrome: any;
export const i18n = createI18n();
// Keep service worker alive
setTimeout(() => {
chrome.runtime.getPlatformInfo();
}, 20e3);
(async () => {
const results: Record<string, any> = {};
const runBench = async (bench: Bench) => {
await reportProgress(`[start] ${bench.name}`);
await bench.run();
results[bench.name!] = bench.table();
await reportProgress(`[done] ${bench.name}`);
};
{
const key = 'simple';
const simple = new Bench({ name: 'Simple' })
.add('Vanilla', () => void chrome.i18n.getMessage(key))
.add('WXT I18n', () => void i18n.t(key));
await runBench(simple);
}
{
const key = 'substitution';
const value = 'test';
const substitution = new Bench({ name: 'Substitution' })
.add('Vanilla', () => void chrome.i18n.getMessage(key, [value]))
.add('WXT I18n', () => void i18n.t(key, [value]));
await runBench(substitution);
}
{
const vanillaPluralKey = 'plural';
const wxtKey = 'wxtPlural';
const one = 1;
const pluralSingular = new Bench({
name: 'Plural (singular form)',
})
.add(
'Vanilla',
() => void chrome.i18n.getMessage(vanillaPluralKey, [one]),
)
.add('WXT I18n', () => void i18n.t(wxtKey, one));
await runBench(pluralSingular);
const two = 2;
const vanillaSingularKey = 'singular';
const pluralPlural = new Bench({
name: 'Plural (plural form)',
time: 1000,
})
.add(
'Vanilla',
() => void chrome.i18n.getMessage(vanillaSingularKey, [two]),
)
.add('WXT I18n', () => void i18n.t(wxtKey, two));
await runBench(pluralPlural);
}
// Report results
await reportResults(results);
})();
async function reportProgress(message: string) {
const res = await fetch('http://localhost:3000/progress', {
method: 'POST',
body: message,
});
if (!res.ok) throw Error('Progress report failed...');
}
async function reportResults(results: any) {
const res = await fetch('http://localhost:3000/results', {
method: 'POST',
body: JSON.stringify(results, null, 2),
});
if (!res.ok) throw Error('Results report failed...');
}
+11
View File
@@ -0,0 +1,11 @@
{
"$schema": "https://json.schemastore.org/chrome-manifest",
"name": "WXT I18n Benchmark",
"version": "1.0.0",
"manifest_version": 3,
"default_locale": "en",
"background": {
"type": "module",
"service_worker": "dist/background.js"
}
}
+48
View File
@@ -0,0 +1,48 @@
import { join, relative } from 'node:path';
const distDir = join(import.meta.dir, 'dist');
const backgroundSrc = join(import.meta.dir, 'background.ts');
console.log('\nBuilding benchmark extension...');
await Bun.build({
entrypoints: [backgroundSrc],
outdir: distDir,
format: 'esm',
});
console.log('Done!');
console.log(
`\nInstall the extension from ./${relative(process.cwd(), import.meta.dir)} (or reload it) to run benchmarks.`,
);
console.log('Waiting for benchmark results...');
const CORS_HEADERS = {
'Access-Control-Allow-Origin': '*',
};
Bun.serve({
fetch: async (request) => {
// CORS support
if (request.method === 'OPTIONS') {
return new Response(undefined, { headers: CORS_HEADERS });
}
const url = new URL(request.url);
if (url.pathname === '/progress') {
console.log(`\x1b[2m← ${await request.text()}\x1b[0m`);
return new Response(undefined, { status: 202, headers: CORS_HEADERS });
}
if (url.pathname === '/results') {
const body = await request.json();
for (const [name, table] of Object.entries(body)) {
console.log('\n' + name);
console.table(table);
}
setTimeout(() => void process.exit(0));
return new Response(undefined, { status: 202, headers: CORS_HEADERS });
}
return new Response(undefined, { status: 404, headers: CORS_HEADERS });
},
});
+2
View File
@@ -24,6 +24,7 @@
"build": "buildc -- tsdown",
"check": "buildc --deps-only -- check",
"test": "buildc --deps-only -- vitest",
"bench": "buildc --deps-only -- bun run bench/run.ts",
"test:coverage": "bun run test run --coverage",
"prepack": "bun run build"
},
@@ -46,6 +47,7 @@
"@types/node": "catalog:",
"oxlint": "catalog:",
"publint": "catalog:",
"tinybench": "^6.0.1",
"tsdown": "catalog:",
"typescript": "catalog:",
"vitest": "catalog:",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"types": ["node"]
"types": ["bun"]
},
"exclude": ["node_modules/**", "dist/**"]
}