haikuwebkit/PerformanceTests/RexBench/driver.js

206 lines
6.9 KiB
JavaScript
Raw Permalink Normal View History

Create a new JavaScript RegExp benchmark https://bugs.webkit.org/show_bug.cgi?id=175225 Reviewed by JF Bastien. This is a new benchmark for Regular Expressions. It borrows regex-dna from SunSpider, the regexp test from Octane2, the BASIC parser from ARES-6/Basic, and adds a new flight planner benchmark that uses RegExp's for textual parsing. There needs to be some additions and changes to some of the textual content. This includes adding more BASIC programs to the Basic test and increasing keyword usage in the Flight Planner to increase the 16-bit coverage. The intent is to grow this benchmark by adding a JavaScript implementation of the offline assembler lexer and parser as well as adding some targeted micro benchmark tests. * RexBench: Added. * RexBench/Basic: Added. * RexBench/Basic/ast.js: Added. * RexBench/Basic/basic.js: Added. * RexBench/Basic/benchmark.js: Added. * RexBench/Basic/caseless_map.js: Added. * RexBench/Basic/lexer.js: Added. * RexBench/Basic/number.js: Added. * RexBench/Basic/parser.js: Added. * RexBench/Basic/random.js: Added. * RexBench/Basic/state.js: Added. * RexBench/Basic/stress-test.js: Added. * RexBench/Basic/util.js: Added. * RexBench/FlightPlanner: Added. * RexBench/FlightPlanner/airways.js: Added. * RexBench/FlightPlanner/benchmark.js: Added. * RexBench/FlightPlanner/convert-nfdc.py: Added. * RexBench/FlightPlanner/expectations.js: Added. * RexBench/FlightPlanner/flight_planner.js: Added. * RexBench/FlightPlanner/use_unicode.js: Added. * RexBench/FlightPlanner/waypoints.js: Added. * RexBench/Octane2: Added. * RexBench/Octane2/base.js: Added. * RexBench/Octane2/regexp.js: Added. * RexBench/SunSpider: Added. * RexBench/SunSpider/regex-dna.js: Added. * RexBench/about.html: Added. * RexBench/basic_benchmark.js: Added. * RexBench/cli.js: Added. * RexBench/driver.js: Added. * RexBench/flightplan_benchmark.js: Added. * RexBench/flightplan_unicode_benchmark.js: Added. * RexBench/glue.js: Added. * RexBench/index.html: Added. * RexBench/octane2_benchmark.js: Added. * RexBench/results.js: Added. * RexBench/stats.js: Added. * RexBench/styles.css: Added. * RexBench/sunspider_benchmark.js: Added. Canonical link: https://commits.webkit.org/191963@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@220307 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-08-05 00:20:23 +00:00
/*
* Copyright (C) 2016-2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
"use strict";
class Driver {
constructor(statusCell, triggerCell, triggerLink, magicCell, summaryCell, key)
{
this._benchmarks = new Map();
this._statusCell = statusCell;
this._triggerCell = triggerCell;
this._triggerLink = triggerLink;
this._magicCell = magicCell;
this._summary = new Stats(summaryCell, "summary");
this._key = key;
if (isInBrowser)
window[key] = this;
}
addBenchmark(benchmark)
{
this._benchmarks.set(benchmark, new Results(benchmark));
}
readyTrigger()
{
if (isInBrowser) {
this._triggerCell.addEventListener('click', this._triggerLink);
this._triggerCell.classList.add('ready');
}
}
disableTrigger()
{
if (isInBrowser) {
this._triggerCell.removeEventListener('click', this._triggerLink);
this._triggerCell.classList.remove('ready');
}
}
start(numIterations)
{
this.disableTrigger();
this._updateIterations();
this._summary.reset();
for (let [benchmark, results] of this._benchmarks)
results.reset();
this._isRunning = true;
this._startIterations = this._numIterations = numIterations;
this._iterator = null;
this._iterate();
}
reportResult(...args)
{
this._benchmarks.get(this._benchmark).reportResult(...args);
this._recomputeSummary();
this._iterate();
}
reportError(...args)
{
if (isInBrowser)
console.log("Error encountered: ", ...args);
this._benchmarks.get(this._benchmark).reportError(...args);
if (isInBrowser) {
this._statusCell.innerHTML = "Test failure \u2014 error in console";
this._statusCell.classList.add("failed");
} else
print("Test failure");
}
_recomputeSummary()
{
class Geomean {
constructor()
{
this._count = 0;
this._sum = 0;
}
add(value)
{
this._count++;
this._sum += Math.log(value);
}
get result()
{
return Math.exp(this._sum * (1 / this._count));
}
}
let statses = [];
for (let results of this._benchmarks.values()) {
for (let subResult of Results.subResults)
statses.push(results[subResult]);
}
let numIterations = Math.min(...statses.map(stats => stats.numIterations));
let data = new Array(numIterations);
for (let i = 0; i < data.length; ++i)
data[i] = new Geomean();
for (let stats of statses) {
for (let i = 0; i < data.length; ++i)
data[i].add(stats.valueForIteration(i));
}
let geomeans = data.map(geomean => geomean.result);
this._summary.reset(...geomeans);
}
_iterate()
{
this._benchmark = this._iterator ? this._iterator.next().value : null;
if (!this._benchmark) {
if (!this._numIterations) {
if (isInBrowser) {
this._statusCell.innerHTML = "Restart";
this.readyTrigger();
} else
print("Success! Benchmark is now finished.");
return;
}
this._numIterations--;
this._updateIterations();
this._iterator = this._benchmarks.keys();
this._benchmark = this._iterator.next().value;
}
this._benchmarks.get(this._benchmark).reportRunning();
let benchmark = this._benchmark;
if (isInBrowser) {
window.setTimeout(() => {
if (!this._isRunning)
return;
this._magicCell.contentDocument.body.textContent = "";
this._magicCell.contentDocument.body.innerHTML = "<iframe id=\"magicFrame\" frameborder=\"0\">";
let magicFrame = this._magicCell.contentDocument.getElementById("magicFrame");
magicFrame.contentDocument.open();
magicFrame.contentDocument.write(
`<!DOCTYPE html><head><title>benchmark payload</title></head><body><script>` +
`window.onerror = top.${this._key}.reportError.bind(top.${this._key});\n` +
`function reportResult()\n` +
`{\n` +
` var driver = top.${this._key};\n` +
` driver.reportResult.apply(driver, arguments);\n` +
`}\n` +
`</script>\n` +
`${this._benchmark.code}</body></html>`);
}, 100);
} else {
Promise.resolve(20).then(() => {
if (!this._isRunning)
return;
try {
print(`Running... ${this._benchmark.name} ( ${this._numIterations + 1} to go)`);
benchmark.run();
print("\n");
} catch(e) {
print(e);
print(e.stack);
}
});
}
}
_updateIterations()
{
if (isInBrowser) {
this._statusCell.innerHTML = "Running Tests... " + ( this._startIterations - this._numIterations ) + "/" + this._startIterations;
}
}
}