You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 lines
3.2 KiB
Plaintext

#!/usr/bin/env node
/* eslint camelcase:0, max-len:0, one-var:0 */
//
// Measures impact of a Git commit (or multiple commits) on generated parsers
// speed and size. Makes sense to use only on PEG.js git repository checkout.
//
"use strict";
let child_process = require("child_process");
let fs = require("fs");
let os = require("os");
let path = require("path");
let glob = require("glob");
// Current Working Directory
let cwd = path.join(__dirname, "..");
if (process.cwd() !== cwd) {
process.chdir(cwd);
}
// Execution Files
let PEGJS_BIN = "bin/peg.js";
let BENCHMARK_BIN = "test/benchmark/run";
if (!fs.existsSync(PEGJS_BIN)) {
PEGJS_BIN = "bin/pegjs";
}
if (!fs.existsSync(BENCHMARK_BIN)) {
BENCHMARK_BIN = "benchmark/run";
}
// Utils
let print = console.log;
function echo(message) {
process.stdout.write(message);
}
function exec(command) {
return child_process.execSync(command, { encoding: "utf8" });
}
function prepare(commit) {
exec(`git checkout --quiet "${commit}"`);
}
function runBenchmark() {
return parseFloat(
exec("node " + BENCHMARK_BIN)
// Split by table seprator, reverse and return the total bytes per second
.split("│")
.reverse()[1]
// Trim the whitespaces and remove ` kB/s` from the end
.trim()
.slice(0, -5)
);
}
function measureSpeed() {
return (runBenchmark() + runBenchmark() + runBenchmark() + runBenchmark() + runBenchmark() / 5).toFixed(2);
}
function measureSize() {
let size = 0;
glob.sync("examples/*.pegjs")
.forEach(example => {
exec(`node ${PEGJS_BIN} ${example}`);
example = example.slice(0, -5) + "js";
size += fs.statSync(example).size;
fs.unlinkSync(example);
});
return size;
}
function difference($1, $2) {
return (($2 / $1 - 1) * 100).toFixed(4);
}
// Prepare
let argv = process.argv.slice(2);
let commit_before, commit_after;
if (argv.length === 1) {
commit_before = argv[0] + "~1";
commit_after = argv[0];
} else if (argv.length === 2) {
commit_before = argv[0];
commit_after = argv[1];
} else {
print("Usage:");
print("");
print(" test/impact <commit>");
print(" test/impact <commit_before> <commit_after>");
print("");
print("Measures impact of a Git commit (or multiple commits) on generated parsers'");
print("speed and size. Makes sense to use only on PEG.js Git repository checkout.");
print("");
process.exit(1);
}
// Measure
let branch = exec("git rev-parse --abbrev-ref HEAD");
let speed1, size1, speed2, size2;
echo(`Measuring commit ${commit_before}...`);
prepare(commit_before);
speed1 = measureSpeed();
size1 = measureSize();
echo(" OK" + os.EOL);
echo(`Measuring commit ${commit_after}...`);
prepare(commit_after);
speed2 = measureSpeed();
size2 = measureSize();
echo(" OK" + os.EOL);
// Finish
prepare(branch);
print(`
test/impact ${commit_before} ${commit_after}
Speed impact
------------
Before: ${speed1} kB/s
After: ${speed2} kB/s
Difference: ${difference(parseFloat(speed1), parseFloat(speed2))}%
Size impact
-----------
Before: ${size1} b
After: ${size2} b
Difference: ${difference(size1, size2)}%
- Measured by /test/impact with Node.js ${process.version}
- Your system: ${os.type()} ${os.release()} ${os.arch()}.
`);