Skip to content
This repository has been archived by the owner on Dec 29, 2022. It is now read-only.

Adding a simple benchmark runner HTML page and node script. #123

Merged
merged 1 commit into from Dec 14, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
130 changes: 130 additions & 0 deletions scripts/run-benchmarks.js
@@ -0,0 +1,130 @@
#!/usr/bin/env node
/**
* Copyright 2012 Google, Inc. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

/**
* @fileoverview node.js runner.
*
* @author benvanik@google.com (Ben Vanik)
*/

var fs = require('fs');
var vm = require('vm');

var benchmark = require('../src/wtf/testing/benchmark');
var benchmarkList = require('../test/benchmarks').value;

global.benchmark = benchmark;
global.wtf = require('../build-out/wtf_node_js_compiled');


function padLeft(value, width) {
value = String(value);
while (value.length < width) {
value = value + ' ';
}
return value;
};


function padRight(value, width) {
value = String(value);
while (value.length < width) {
value = ' ' + value;
}
return value;
};


var PAD_RIGHT = 14;


/**
* Logs a benchmark error.
* @param {string} msg Message.
* @param {string=} opt_benchmarkName Benchmark that was running when the error
* occurred.
*/
global.reportBenchmarkError = function(msg, opt_benchmarkName) {
console.log(msg);
};


/**
* Logs a benchmark result.
* @param {string} benchmarkName Benchmark name.
* @param {{
* runCount: number,
* totalTime: number,
* userTime: number,
* meanTime: number
* }} data Result data.
*/
global.reportBenchmarkResult = function(benchmarkName, data) {
console.log(
padLeft(benchmarkName, 32) + ' ' +
padRight(data.runCount, PAD_RIGHT) + ' ' +
padRight((data.totalTime * 1000).toFixed(3) + 'ms', PAD_RIGHT) + ' ' +
padRight((data.meanTime * 1000).toFixed(5) + 'ms', PAD_RIGHT));
};


// Get the list of tests to run.
var benchmarkNames = process.argv.slice(2);

// Remove bad entries.
for (var n = benchmarkNames.length - 1; n >= 0; n--) {
if (!benchmarkNames[n].length) {
benchmarkNames.splice(n, 1);
}
}

// If nothing provided, run all tests.
if (!benchmarkNames.length) {
for (var n = 0; n < benchmarkList.length; n++) {
var entry = benchmarkList[n];
if (entry) {
benchmarkNames.push(entry.name);
}
}
}

// TODO(benvanik): fuzzy search through testNames - if any contain *, lookup
// deps to find all matching namespaces.

// Sort test names.
// TODO(benvanik): sort by namespaces?
benchmarkNames.sort(function(a, b) {
return a < b;
});

// Require all benchmark files.
for (var n = 0; n < benchmarkNames.length; n++) {
var name = benchmarkNames[n];
var entry = null;
for (var m = 0; m < benchmarkList.length; m++) {
if (benchmarkList[m] && benchmarkList[m].name == name) {
entry = benchmarkList[m];
break;
}
}
if (entry) {
var scriptUrl = './test/benchmarks/' + entry.script;
vm.runInThisContext(fs.readFileSync(scriptUrl), scriptUrl);
} else {
reportBenchmarkError('Benchmark entry not found: ' + name);
}
}

console.log(
padLeft('[name]', 32) + ' ' +
padRight('[count]', PAD_RIGHT) + ' ' +
padRight('[total]', PAD_RIGHT) + ' ' +
padRight('[mean]', PAD_RIGHT));

// Launch the run.
benchmark.run.apply(null, benchmarkNames);
24 changes: 24 additions & 0 deletions scripts/run-benchmarks.sh
@@ -0,0 +1,24 @@
#!/bin/bash

# Copyright 2012 Google Inc. All Rights Reserved.

# Run benchmarks quickly.
# This requires up-to-date deps files, produced by 'anvil build :deps'.
#
# If trying to test in an automated environment, prefer using the :test rule:
# anvil build :test


# Fast build and ensure test dependencies exist.
./third_party/anvil-build/anvil-local.sh build :debug :release


GREP="$1"
if [ -z $GREP ]; then
GREP=""
echo "Running all benchmarks..."
else
echo "Running benchmarks matching '$GREP'..."
fi

./scripts/run-benchmarks.js $GREP
14 changes: 14 additions & 0 deletions scripts/update-benchmarks.sh
@@ -0,0 +1,14 @@
#!/bin/bash

# Copyright 2012 Google Inc. All Rights Reserved.

# Updates the benchmarks index file, used to select and run benchmarks.

# This must currently run from the root of the repo
# TODO(benvanik): make this runnable from anywhere (find git directory?)
if [ ! -d ".git" ]; then
echo "This script must be run from the root of the repository (the folder containing .git)"
exit 1
fi

# TODO(benvanik): list *.js, see if it contains any benchmark.register() functions
179 changes: 179 additions & 0 deletions src/wtf/testing/benchmark.html
@@ -0,0 +1,179 @@
<!DOCTYPE html>
<html>
<head>
<title>wtf benchmark</title>
<script src="../../../wtf_trace_web_js_compiled.js"></script>
<script src="../../../node_modules/benchmark/benchmark.js"></script>
<script src="benchmark.js"></script>
<script src="../../../test/benchmarks.js"></script>
</head>
<body>
<table id="results">
<tr>
<td>[name]</td>
<td>[count]</td>
<td>[total]</td>
<td>[mean]</td>
</tr>
</table>
<script>

/**
* Injects a function into the page.
* @param {!Function} fn Function to inject.
* @param {Array=} opt_args Arguments array. All must be string serializable.
*/
function injectScriptFunction(fn, opt_args) {
// Header to let users know what's up.
var header = [
'/* Web Tracing Framework injected benchmark function: ' + fn.name + ' */'
].join('\n');

// Format args as strings that can go in the source.
var args = opt_args || [];
for (var n = 0; n < args.length; n++) {
if (typeof args[n] == 'string') {
// TODO(benvanik): escape
args[n] = '"' + args[n] + '"';
}
}
args = args.join(',');

// TODO(benvanik): escape fn source
var source = String(fn);

// Create script tag.
document.write('<script>' + header + '\n\n(' + source + ')(' + args + ');' +
'</sc' + 'ript>');
};


/**
* Sets up the benchmarks, loading the list and beginning the tests.
*/
function setupTesting() {
// Get the list of tests to run.
var benchmarkNames = [];
var query = window.location.search;
if (query.length) {
query = query.substring(1);
query = query.split('&')
}
for (var n = 0; n < query.length; n++) {
var tuple = query[n].split('=');
switch (tuple[0]) {
case 'tests':
benchmarkNames = tuple[1].split(',');
break;
}
}

// Remove bad entries.
for (var n = benchmarkNames.length - 1; n >= 0; n--) {
if (!benchmarkNames[n].length) {
benchmarkNames.splice(n, 1);
}
}

// If nothing provided, run all tests.
if (!benchmarkNames.length) {
for (var n = 0; n < benchmarkList.length; n++) {
var entry = benchmarkList[n];
if (entry) {
benchmarkNames.push(entry.name);
}
}
}

// TODO(benvanik): fuzzy search through testNames - if any contain *, lookup
// deps to find all matching namespaces.

// Sort test names.
// TODO(benvanik): sort by namespaces?
benchmarkNames.sort(function(a, b) {
return a < b;
});

// Set page title.
var prettyNames = [];
for (var n = 0; n < benchmarkNames.length; n++) {
prettyNames.push(benchmarkNames[n].replace('_test', ''));
}
document.title = 'WTF Benchmark: ' + prettyNames.join(', ');

// Require all benchmark files.
for (var n = 0; n < benchmarkNames.length; n++) {
var name = benchmarkNames[n];
var entry = null;
for (var m = 0; m < benchmarkList.length; m++) {
if (benchmarkList[m] && benchmarkList[m].name == name) {
entry = benchmarkList[m];
break;
}
}
if (entry) {
var scriptUrl = '../../../test/benchmarks/' + entry.script;
document.write('<script src="' + scriptUrl + '"></sc' + 'ript>');
} else {
reportBenchmarkError('Benchmark entry not found: ' + name);
}
}

// Launch the run.
injectScriptFunction(function(benchmarkNames) {
benchmark.run(benchmarkNames);
}, benchmarkNames);
}


/**
* Logs a benchmark error.
* @param {string} msg Message.
* @param {string=} opt_benchmarkName Benchmark that was running when the error
* occurred.
*/
function reportBenchmarkError(msg, opt_benchmarkName) {
if (window.console) {
window.console.log(msg);
}

var errorDiv = document.createElement('div');
errorDiv.id = 'error';
errorDiv.innerText = msg;
document.body.insertBefore(errorDiv, document.body.firstChild);
};


/**
* Logs a benchmark result.
* @param {string} benchmarkName Benchmark name.
* @param {{
* runCount: number,
* totalTime: number,
* userTime: number,
* meanTime: number
* }} data Result data.
*/
function reportBenchmarkResult(benchmarkName, data) {
if (window.console) {
window.console.log(benchmarkName, data);
}

var row = document.createElement('tr');
row.innerHTML = [
'<td>' + benchmarkName + '</td>',
'<td>' + data.runCount + '</td>',
'<td>' + (data.totalTime * 1000).toFixed(3) + 'ms' + '</td>',
'<td>' + (data.meanTime * 1000).toFixed(5) + 'ms' + '</td>'
].join('');

var resultsEl = document.getElementById('results');
resultsEl.appendChild(row);
};


setupTesting();

</script>
</body>
</html>