import { execSync } from "node:child_process";
import { existsSync, readdirSync, rmSync, statSync } from "node:fs";
import { join } from "node:path";
const ITERATIONS = 5;
const WARMUP_RUNS = 1;
const tools = [
{ name: "esbuild", cmd: "node esbuild.config.js" },
{ name: "tsup", cmd: "tsup --config bench-js/tsup.config.ts" },
{ name: "rollup", cmd: "rollup -c bench-js/rollup.config.js" },
{ name: "vite", cmd: "vite build --config bench-js/vite.config.ts" },
];
function cleanDist() {
rmSync("dist-js", { recursive: true, force: true });
}
function getOutputSize() {
if (!existsSync("dist-js")) return 0;
let total = 0;
const files = readdirSync("dist-js");
for (const file of files) {
const stat = statSync(join("dist-js", file));
total += stat.size;
}
return total;
}
function runBuild(cmd) {
const start = performance.now();
try {
execSync(cmd, { stdio: "pipe", encoding: "utf-8" });
const end = performance.now();
return { success: true, time: end - start };
} catch (error) {
return { success: false, time: 0, error: error.message };
}
}
function formatTime(ms) {
if (ms < 1000) return `${ms.toFixed(0)}ms`;
return `${(ms / 1000).toFixed(2)}s`;
}
function formatSize(bytes) {
if (bytes < 1024) return `${bytes}B`;
return `${(bytes / 1024).toFixed(1)}KB`;
}
console.log("╔══════════════════════════════════════════════════════════════╗");
console.log("║ Build Tool Benchmark - tauri-plugin-profiling ║");
console.log("╠══════════════════════════════════════════════════════════════╣");
console.log(
`║ Iterations: ${ITERATIONS} (+ ${WARMUP_RUNS} warmup) ║`,
);
console.log("╚══════════════════════════════════════════════════════════════╝");
console.log();
const results = [];
for (const tool of tools) {
process.stdout.write(`Benchmarking ${tool.name}...`);
for (let i = 0; i < WARMUP_RUNS; i++) {
cleanDist();
runBuild(tool.cmd);
}
const times = [];
let outputSize = 0;
let failed = false;
for (let i = 0; i < ITERATIONS; i++) {
cleanDist();
const result = runBuild(tool.cmd);
if (!result.success) {
console.log(" FAILED");
console.log(` Error: ${result.error?.slice(0, 100)}`);
failed = true;
break;
}
times.push(result.time);
if (i === 0) outputSize = getOutputSize();
}
if (failed) {
results.push({ name: tool.name, failed: true });
continue;
}
const avg = times.reduce((a, b) => a + b, 0) / times.length;
const min = Math.min(...times);
const max = Math.max(...times);
results.push({
name: tool.name,
avg,
min,
max,
outputSize,
failed: false,
});
console.log(` ${formatTime(avg)} avg`);
}
console.log();
console.log("╔══════════════════════════════════════════════════════════════╗");
console.log("║ RESULTS ║");
console.log("╠══════════════════════════════════════════════════════════════╣");
const sorted = results.filter((r) => !r.failed).sort((a, b) => a.avg - b.avg);
const fastest = sorted[0]?.avg || 1;
console.log("║ Tool │ Avg Time │ Min │ Max │ Size ║");
console.log("╠════════════╪════════════╪══════════╪══════════╪═══════════╣");
for (const r of sorted) {
const speedup = r.avg / fastest;
const speedupStr = speedup === 1 ? "fastest" : `${speedup.toFixed(1)}x`;
const name = r.name.padEnd(10);
const avg = formatTime(r.avg).padStart(8);
const min = formatTime(r.min).padStart(6);
const max = formatTime(r.max).padStart(6);
const size = formatSize(r.outputSize).padStart(7);
console.log(`║ ${name}│ ${avg} │ ${min} │ ${max} │ ${size} ║`);
}
for (const r of results.filter((r) => r.failed)) {
const name = r.name.padEnd(10);
console.log(`║ ${name}│ FAILED │ - │ - │ - ║`);
}
console.log("╚══════════════════════════════════════════════════════════════╝");
console.log();
if (sorted.length > 0) {
const winner = sorted[0];
const slowest = sorted[sorted.length - 1];
const speedup = (slowest.avg / winner.avg).toFixed(1);
console.log(`🏆 Winner: ${winner.name} (${formatTime(winner.avg)} avg)`);
console.log(
` ${speedup}x faster than ${slowest.name} (${formatTime(slowest.avg)} avg)`,
);
}
console.log();
console.log("## Markdown table for README:");
console.log();
console.log("| Tool | Avg Time | Min | Max | Output Size |");
console.log("|------|----------|-----|-----|-------------|");
for (const r of sorted) {
console.log(
`| ${r.name} | ${formatTime(r.avg)} | ${formatTime(r.min)} | ${formatTime(r.max)} | ${formatSize(r.outputSize)} |`,
);
}