Skip to content

Commit b2c050b

Browse files
committed
test(benchmark): add test runner and stubs for bp.js
This commit adds a karma setup with a spec file for bp.js, and has refactored bp.js to expose all functions on a global "bp" object. Behavior of functions hasn't changed, other than to remove some duplication of code regarding adding buttons to the DOM.
1 parent 447ee6c commit b2c050b

File tree

3 files changed

+240
-112
lines changed

3 files changed

+240
-112
lines changed

benchmark/karma.conf.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Karma configuration
2+
// Generated on Tue Jun 10 2014 08:41:10 GMT-0700 (PDT)
3+
4+
module.exports = function(config) {
5+
config.set({
6+
7+
// base path, that will be used to resolve files and exclude
8+
basePath: '',
9+
10+
11+
// frameworks to use
12+
frameworks: ['jasmine'],
13+
14+
15+
// list of files / patterns to load in the browser
16+
files: [
17+
'web/*.js'
18+
],
19+
20+
21+
// list of files to exclude
22+
exclude: [
23+
24+
],
25+
26+
27+
// test results reporter to use
28+
// possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
29+
reporters: ['progress'],
30+
31+
32+
// web server port
33+
port: 9876,
34+
35+
36+
// enable / disable colors in the output (reporters and logs)
37+
colors: true,
38+
39+
40+
// level of logging
41+
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
42+
logLevel: config.LOG_INFO,
43+
44+
45+
// enable / disable watching file and executing tests whenever any file changes
46+
autoWatch: true,
47+
48+
49+
// Start these browsers, currently available:
50+
// - Chrome
51+
// - ChromeCanary
52+
// - Firefox
53+
// - Opera
54+
// - Safari (only Mac)
55+
// - PhantomJS
56+
// - IE (only Windows)
57+
browsers: ['Chrome'],
58+
59+
60+
// If browser does not capture in given timeout [ms], kill it
61+
captureTimeout: 60000,
62+
63+
64+
// Continuous Integration mode
65+
// if true, it capture browsers, run tests and exit
66+
singleRun: false
67+
});
68+
};

benchmark/web/bp.js

Lines changed: 121 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,112 @@
1-
window.benchmarkSteps = [];
1+
var bp = window.bp = {};
2+
bp.steps = window.benchmarkSteps = [];
3+
bp.timesPerAction = {};
4+
bp.running = false;
5+
bp.numSamples = 10;
6+
7+
bp.numMilliseconds = function() {
8+
if (window.performance != null && typeof window.performance.now == 'function') {
9+
return window.performance.now();
10+
} else if (window.performance != null && typeof window.performance.webkitNow == 'function') {
11+
return window.performance.webkitNow();
12+
} else {
13+
console.log('using Date.now');
14+
return Date.now();
15+
}
16+
};
17+
18+
bp.loopBenchmark = function loopBenchmark() {
19+
if (bp.running) {
20+
bp.loopBtn.innerText = 'Loop';
21+
bp.running = false;
22+
} else {
23+
window.requestAnimationFrame(function() {
24+
bp.loopBtn.innerText = 'Pause';
25+
bp.running = true;
26+
var loopB = function() {
27+
if (bp.running) {
28+
window.requestAnimationFrame(function() {
29+
if (bp.running) bp.runBenchmarkSteps(loopB);
30+
});
31+
}
32+
};
33+
loopB();
34+
});
35+
}
36+
};
37+
38+
bp.onceBenchmark = function() {
39+
var btn = bp.onceBtn;
40+
window.requestAnimationFrame(function() {
41+
btn.innerText = '...';
42+
window.requestAnimationFrame(function() {
43+
bp.runBenchmarkSteps(function() {
44+
btn.innerText = 'Once';
45+
});
46+
});
47+
});
48+
};
49+
50+
bp.runBenchmarkSteps = function runBenchmarkSteps(done) {
51+
// Run all the steps;
52+
var times = {};
53+
bp.steps.forEach(function(bs) {
54+
if (typeof window.gc === 'function') {
55+
window.gc();
56+
}
57+
var startTime = bp.numMilliseconds();
58+
bs.fn();
59+
times[bs.name] = bp.numMilliseconds() - startTime;
60+
});
61+
bp.calcStats(times);
62+
63+
done();
64+
};
65+
66+
bp.calcStats = function calcStats(times) {
67+
var iH = '';
68+
bp.steps.forEach(function(bs) {
69+
var tpa = bp.timesPerAction[bs.name];
70+
if (!tpa) {
71+
tpa = bp.timesPerAction[bs.name] = {
72+
times: [], // circular buffer
73+
fmtTimes: [],
74+
nextEntry: 0
75+
}
76+
}
77+
tpa.fmtTimes[tpa.nextEntry] = ('' + times[bs.name]).substr(0,6);
78+
tpa.times[tpa.nextEntry++] = times[bs.name];
79+
tpa.nextEntry %= bp.numSamples;
80+
var avg = 0;
81+
tpa.times.forEach(function(x) { avg += x; });
82+
avg /= Math.min(bp.numSamples, tpa.times.length);
83+
avg = ('' + avg).substr(0,6);
84+
iH += '<div>' + (' ' + bs.name).slice(-10).replace(/ /g, '&nbsp;') + ': avg-' + bp.numSamples + ':<b>' + avg + 'ms</b> [' + tpa.fmtTimes.join(', ') + ']ms</div>';
85+
});
86+
bp.infoDiv.innerHTML = iH;
87+
};
88+
89+
bp.container = function() {
90+
if (!bp._container) {
91+
bp._container = document.querySelector('#benchmarkContainer');
92+
}
93+
return bp._container;
94+
}
95+
96+
bp.addButton = function(reference, text, handler) {
97+
var container = bp.container();
98+
bp[reference] = document.createElement('button');
99+
bp[reference].innerText = text;
100+
101+
bp[reference].addEventListener('click', handler);
2102

3-
window.addEventListener('DOMContentLoaded', function() {
4-
var container = document.querySelector('#benchmarkContainer');
103+
container.appendChild(bp[reference]);
104+
}
5105

106+
bp.addLinks = function() {
6107
// Add links to everything
7108
var linkDiv = document.createElement('div');
8-
linkDiv.style['margin-bottom'] = "1.5em";
109+
linkDiv.style['margin-bottom'] = '1.5em';
9110
var linkHtml = [
10111
'<style>',
11112
'.bpLink { background: lightblue; padding: 1em }',
@@ -14,8 +115,8 @@ window.addEventListener('DOMContentLoaded', function() {
14115
].join('\n');
15116

16117
[
17-
// Add new benchmark suites here
18-
['tree.html', 'TreeComponent']
118+
// Add new benchmark suites here
119+
['tree.html', 'TreeComponent']
19120
].forEach((function (link) {
20121
linkHtml += [
21122
'<a class=bpLink href=',
@@ -27,113 +128,21 @@ window.addEventListener('DOMContentLoaded', function() {
27128
}));
28129

29130
linkDiv.innerHTML = linkHtml;
30-
container.appendChild(linkDiv);
31-
32-
33-
// Benchmark runner
34-
var btn = document.createElement('button');
35-
btn.innerText = "Loop";
36-
var running = false;
37-
btn.addEventListener('click', loopBenchmark);
38-
39-
container.appendChild(btn);
40-
41-
function loopBenchmark() {
42-
if (running) {
43-
btn.innerText = "Loop";
44-
running = false;
45-
} else {
46-
window.requestAnimationFrame(function() {
47-
btn.innerText = "Pause";
48-
running = true;
49-
var loopB = function() {
50-
if (running) {
51-
window.requestAnimationFrame(function() {
52-
if (running) runBenchmarkSteps(loopB);
53-
});
54-
}
55-
};
56-
loopB();
57-
});
58-
}
59-
}
131+
bp.container().appendChild(linkDiv);
132+
};
60133

134+
bp.addInfo = function() {
135+
bp.infoDiv = document.createElement('div');
136+
bp.infoDiv.style['font-family'] = 'monospace';
137+
bp.container().appendChild(bp.infoDiv);
138+
};
61139

62-
var onceBtn = document.createElement('button');
63-
onceBtn.innerText = "Once";
64-
onceBtn.addEventListener('click', function() {
65-
window.requestAnimationFrame(function() {
66-
onceBtn.innerText = "...";
67-
window.requestAnimationFrame(function() {
68-
runBenchmarkSteps(function() {
69-
onceBtn.innerText = "Once";
70-
});
71-
});
72-
});
73-
});
74-
container.appendChild(onceBtn);
75-
76-
var infoDiv = document.createElement('div');
77-
infoDiv.style['font-family'] = 'monospace';
78-
container.appendChild(infoDiv);
140+
bp.onDOMContentLoaded = function() {
141+
bp.addLinks();
142+
bp.addButton('loopBtn', 'Loop', bp.loopBenchmark);
143+
bp.addButton('onceBtn', 'Once', bp.onceBenchmark);
79144

145+
bp.addInfo();
146+
};
80147

81-
var numMilliseconds;
82-
var performance = window.performance;
83-
if (performance != null && typeof performance.now == "function") {
84-
numMilliseconds = function numMillisecondsWPN() {
85-
return performance.now();
86-
}
87-
} else if (performance != null && typeof performance.webkitNow == "function") {
88-
numMilliseconds = function numMillisecondsWebkit() {
89-
return performance.webkitNow();
90-
}
91-
} else {
92-
console.log('using Date.now');
93-
numMilliseconds = function numMillisecondsDateNow() {
94-
return Date.now();
95-
};
96-
}
97-
98-
function runBenchmarkSteps(done) {
99-
// Run all the steps;
100-
var times = {};
101-
window.benchmarkSteps.forEach(function(bs) {
102-
if (typeof window.gc === 'function') {
103-
window.gc();
104-
}
105-
var startTime = numMilliseconds();
106-
bs.fn();
107-
times[bs.name] = numMilliseconds() - startTime;
108-
});
109-
calcStats(times);
110-
111-
done();
112-
}
113-
114-
var timesPerAction = {};
115-
116-
var NUM_SAMPLES = 10;
117-
function calcStats(times) {
118-
var iH = '';
119-
window.benchmarkSteps.forEach(function(bs) {
120-
var tpa = timesPerAction[bs.name];
121-
if (!tpa) {
122-
tpa = timesPerAction[bs.name] = {
123-
times: [], // circular buffer
124-
fmtTimes: [],
125-
nextEntry: 0
126-
}
127-
}
128-
tpa.fmtTimes[tpa.nextEntry] = ('' + times[bs.name]).substr(0,6);
129-
tpa.times[tpa.nextEntry++] = times[bs.name];
130-
tpa.nextEntry %= NUM_SAMPLES;
131-
var avg = 0;
132-
tpa.times.forEach(function(x) { avg += x; });
133-
avg /= Math.min(NUM_SAMPLES, tpa.times.length);
134-
avg = ('' + avg).substr(0,6);
135-
iH += '<div>' + (' ' + bs.name).slice(-10).replace(/ /g, '&nbsp;') + ': avg-' + NUM_SAMPLES + ':<b>' + avg + 'ms</b> [' + tpa.fmtTimes.join(', ') + ']ms</div>';
136-
});
137-
infoDiv.innerHTML = iH;
138-
}
139-
});
148+
window.addEventListener('DOMContentLoaded', bp.onDOMContentLoaded);

benchmark/web/bp.spec.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
describe('bp', function() {
2+
var bp = window.bp;
3+
4+
beforeEach(function() {
5+
bp._container = document.createElement('div');
6+
});
7+
8+
describe('.loopBenchmark()', function() {
9+
10+
});
11+
12+
13+
describe('.onceBenchmark()', function() {
14+
15+
});
16+
17+
18+
describe('.runBenchmarkSteps()', function() {
19+
20+
});
21+
22+
23+
describe('.container()', function() {
24+
25+
});
26+
27+
28+
describe('.addButton()', function() {
29+
30+
});
31+
32+
33+
describe('.addLinks()', function() {
34+
35+
});
36+
37+
38+
describe('.addInfo()', function() {
39+
40+
});
41+
42+
43+
describe('.calcStats()', function() {
44+
45+
});
46+
47+
48+
describe('.onDOMContentLoaded()', function() {
49+
50+
});
51+
});

0 commit comments

Comments
 (0)