#!/usr/bin/env node "use strict"; /* eslint-env node */ /* eslint no-console: 0*/ let Runner = require("./runner.js"); let benchmarks = require("./benchmarks.js"); let fs = require("fs"); // Results Table Manipulation function dup(text, count) { let result = ""; for (let i = 1; i <= count; i++) { result += text; } return result; } function padLeft(text, length) { return dup(" ", length - text.length) + text; } function padRight(text, length) { return text + dup(" ", length - text.length); } function center(text, length) { let padLength = (length - text.length) / 2; return dup(" ", Math.floor(padLength)) + text + dup(" ", Math.ceil(padLength)); } function writeTableHeader() { console.log("┌─────────────────────────────────────┬───────────┬────────────┬──────────────┐"); console.log("│ Test │ Inp. size │ Avg. time │ Avg. speed │"); } function writeHeading(heading) { console.log("├─────────────────────────────────────┴───────────┴────────────┴──────────────┤"); console.log("│ " + center(heading, 75) + " │"); console.log("├─────────────────────────────────────┬───────────┬────────────┬──────────────┤"); } function writeResult(title, inputSize, parseTime) { const KB = 1024; const MS_IN_S = 1000; console.log("│ " + padRight(title, 35) + " │ " + padLeft((inputSize / KB).toFixed(2), 6) + " kB │ " + padLeft(parseTime.toFixed(2), 7) + " ms │ " + padLeft(((inputSize / KB) / (parseTime / MS_IN_S)).toFixed(2), 7) + " kB/s │" ); } function writeSeparator() { console.log("├─────────────────────────────────────┼───────────┼────────────┼──────────────┤"); } function writeTableFooter() { console.log("└─────────────────────────────────────┴───────────┴────────────┴──────────────┘"); } // Helpers function printHelp() { console.log("Usage: run [options]"); console.log(""); console.log("Runs PEG.js benchmark suite."); console.log(""); console.log("Options:"); console.log(" -n, --run-count number of runs (default: 10)"); console.log(" --cache make tested parsers cache results"); console.log(" -o, --optimize select optimization for speed or size (default:"); console.log(" speed)"); } function exitSuccess() { process.exit(0); } function exitFailure() { process.exit(1); } function abort(message) { console.error(message); exitFailure(); } // Arguments let args = process.argv.slice(2); // Trim "node" and the script path. function isOption(arg) { return (/^-/).test(arg); } function nextArg() { args.shift(); } // Main let runCount = 10; let options = { cache: false, optimize: "speed" }; while (args.length > 0 && isOption(args[0])) { switch (args[0]) { case "-n": case "--run-count": nextArg(); if (args.length === 0) { abort("Missing parameter of the -n/--run-count option."); } runCount = parseInt(args[0], 10); if (isNaN(runCount) || runCount <= 0) { abort("Number of runs must be a positive integer."); } break; case "--cache": options.cache = true; break; case "-o": case "--optimize": nextArg(); if (args.length === 0) { abort("Missing parameter of the -o/--optimize option."); } if (args[0] !== "speed" && args[0] !== "size") { abort("Optimization goal must be either \"speed\" or \"size\"."); } options.optimize = args[0]; break; case "-h": case "--help": printHelp(); exitSuccess(); break; default: abort("Unknown option: " + args[0] + "."); } nextArg(); } if (args.length > 0) { abort("No arguments are allowed."); } Runner.run(benchmarks, runCount, options, { readFile: function(file) { return fs.readFileSync(__dirname + "/" + file, "utf8"); }, testStart: function() { // Nothing to do. }, testFinish: function(benchmark, test, inputSize, parseTime) { writeResult(test.title, inputSize, parseTime); }, benchmarkStart: function(benchmark) { writeHeading(benchmark.title); }, benchmarkFinish: function(benchmark, inputSize, parseTime) { writeSeparator(); writeResult(benchmark.title + " total", inputSize, parseTime); }, start: function() { writeTableHeader(); }, finish: function(inputSize, parseTime) { writeSeparator(); writeResult("Total", inputSize, parseTime); writeTableFooter(); } });