Skip to content

Commit dfdf67b

Browse files
committed
feat(benchmark): record gc time for each test run
1 parent a98663d commit dfdf67b

File tree

3 files changed

+68
-22
lines changed

3 files changed

+68
-22
lines changed

benchmark/web/bp.js

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ bp.steps = window.benchmarkSteps = [];
33
bp.runState = {
44
numSamples: 10,
55
recentTimePerStep: {},
6+
recentGCTimePerStep: {},
67
timesPerAction: {}
78
};
89

@@ -82,13 +83,25 @@ bp.runTimedTest = function (bs) {
8283
}
8384
var startTime = bp.numMilliseconds();
8485
bs.fn();
85-
return bp.numMilliseconds() - startTime;
86+
var endTime = bp.numMilliseconds() - startTime;
87+
88+
var startGCTime = bp.numMilliseconds();
89+
if (typeof window.gc === 'function') {
90+
window.gc();
91+
}
92+
var endGCTime = bp.numMilliseconds() - startGCTime;
93+
return {
94+
time: endTime,
95+
gcTime: endGCTime
96+
};
8697
};
8798

8899
bp.runAllTests = function (done) {
89100
if (bp.runState.iterations--) {
90101
bp.steps.forEach(function(bs) {
91-
bp.runState.recentTimePerStep[bs.name] = bp.runTimedTest(bs);
102+
var testResults = bp.runTimedTest(bs);
103+
bp.runState.recentTimePerStep[bs.name] = testResults.time;
104+
bp.runState.recentGCTimePerStep[bs.name] = testResults.gcTime;
92105
});
93106
bp.report = bp.calcStats();
94107
bp.writeReport(bp.report);
@@ -103,20 +116,28 @@ bp.runAllTests = function (done) {
103116
}
104117
}
105118

106-
bp.generateReportPartial = function(name, avg, times) {
119+
bp.generateReportPartial = function(name, avg, fmtTimes, gcTimes) {
107120
return bp.interpolateHtml(
108-
'<tr><td>%0</td><td class="average">%1ms</td><td>[%2]ms</td></tr>',
121+
'<tr><td>%0</td><td class="average">test:%1ms<br>gc:%2ms<br>combined: %3ms</td><td>%4</td><td>%5</td></tr>',
109122
[
110123
name,
111-
('' + avg).substr(0,6),
112-
times.join(', ')
124+
('' + avg.time).substr(0,6),
125+
('' + avg.gcTime).substr(0,6),
126+
('' + (avg.time + avg.gcTime)).substr(0,6),
127+
fmtTimes.join('<br>'),
128+
gcTimes.join('<br>')
113129
]);
114130
};
115131

116-
bp.getAverage = function (times, runState) {
117-
var avg = 0;
118-
times.forEach(function(x) { avg += x; });
119-
return avg / times.length;
132+
bp.getAverage = function (times, gcTimes, runState) {
133+
var timesAvg = 0;
134+
var gcAvg = 0;
135+
times.forEach(function(x) { timesAvg += x; });
136+
gcTimes.forEach(function(x) { gcAvg += x; });
137+
return {
138+
gcTime: gcAvg / gcTimes.length,
139+
time: timesAvg / times.length
140+
};
120141
};
121142

122143
bp.writeReport = function(reportContent) {
@@ -129,6 +150,8 @@ bp.getTimesPerAction = function(name) {
129150
tpa = bp.runState.timesPerAction[name] = {
130151
times: [], // circular buffer
131152
fmtTimes: [],
153+
fmtGCTimes: [],
154+
gcTimes: [],
132155
nextEntry: 0
133156
}
134157
}
@@ -149,17 +172,25 @@ bp.calcStats = function() {
149172
bp.steps.forEach(function(bs) {
150173
var stepName = bs.name,
151174
timeForStep = bp.runState.recentTimePerStep[stepName],
175+
gcTimeForStep = bp.runState.recentGCTimePerStep[stepName],
152176
tpa = bp.getTimesPerAction(stepName),
153177
avg;
154178

155-
tpa.fmtTimes[tpa.nextEntry] = ('' + timeForStep).substr(0,6);
179+
tpa.fmtTimes[tpa.nextEntry] = timeForStep.toString().substr(0, 6);
156180
tpa.fmtTimes = bp.rightSizeTimes(tpa.fmtTimes);
181+
182+
tpa.fmtGCTimes[tpa.nextEntry] = gcTimeForStep.toString().substr(0, 6);
183+
tpa.fmtGCTimes = bp.rightSizeTimes(tpa.fmtGCTimes);
184+
185+
tpa.gcTimes[tpa.nextEntry] = gcTimeForStep;
186+
tpa.gcTimes = bp.rightSizeTimes(tpa.gcTimes);
187+
157188
tpa.times[tpa.nextEntry++] = timeForStep;
158189
tpa.times = bp.rightSizeTimes(tpa.times);
159-
tpa.nextEntry %= bp.runState.numSamples;
160-
avg = bp.getAverage(tpa.times, bp.runState);
161190

162-
report += bp.generateReportPartial(stepName, avg, tpa.fmtTimes);
191+
tpa.nextEntry %= bp.runState.numSamples;
192+
avg = bp.getAverage(tpa.times, tpa.gcTimes);
193+
report += bp.generateReportPartial(stepName, avg, tpa.fmtTimes, tpa.fmtGCTimes);
163194
});
164195
return report;
165196
};

benchmark/web/bp.spec.js

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ describe('bp', function() {
2727
bp.runState = {
2828
numSamples: 10,
2929
recentTimePerStep: {},
30+
recentGCTimePerStep: {},
3031
timesPerAction: {}
3132
};
3233
});
@@ -283,7 +284,7 @@ describe('bp', function() {
283284

284285
it('should return the time required to run the test', function() {
285286
var times = {};
286-
expect(typeof bp.runTimedTest(mockStep, times)).toBe('number');
287+
expect(typeof bp.runTimedTest(mockStep, times).time).toBe('number');
287288
});
288289
});
289290

@@ -358,7 +359,10 @@ describe('bp', function() {
358359

359360
describe('.getAverage()', function() {
360361
it('should return the average of a set of numbers', function() {
361-
expect(bp.getAverage([100,0,50,75,25])).toBe(50);
362+
expect(bp.getAverage([100,0,50,75,25], [2,4,2,4,3])).toEqual({
363+
gcTime: 3,
364+
time: 50
365+
});
362366
});
363367
});
364368

@@ -372,27 +376,37 @@ describe('bp', function() {
372376
recentTimePerStep: {
373377
fakeStep: 5
374378
},
379+
recentGCTimePerStep: {
380+
fakeStep: 2
381+
},
375382
timesPerAction: {
376383
fakeStep: {
377384
times: [3,7],
378385
fmtTimes: ['3', '7'],
386+
fmtGCTimes: ['1','3'],
387+
gcTimes: [1,3],
379388
nextEntry: 2
380389
},
381390
}
382391
};
383392
});
384393

394+
385395
it('should call generateReportPartial() with the correct info', function() {
386396
var spy = spyOn(bp, 'generateReportPartial');
387397
bp.calcStats();
388-
expect(spy).toHaveBeenCalledWith('fakeStep', 5, ['3','7','5']);
398+
expect(spy).toHaveBeenCalledWith('fakeStep', {time: 5, gcTime: 2}, ['3','7','5'], ['1','3','2'])
399+
expect(spy.calls[0].args[0]).toBe('fakeStep');
400+
expect(spy.calls[0].args[1].gcTime).toBe(2);
401+
expect(spy.calls[0].args[1].time).toBe(5);
402+
expect(spy.calls[0].args[2]).toEqual(['3','7', '5']);
389403
});
390404

391405

392406
it('should call getAverage() with the correct info', function() {
393-
var spy = spyOn(bp, 'getAverage');
407+
var spy = spyOn(bp, 'getAverage').andCallThrough();
394408
bp.calcStats();
395-
expect(spy).toHaveBeenCalledWith([3,7,5], bp.runState);
409+
expect(spy).toHaveBeenCalledWith([ 3, 7, 5 ], [ 1, 3, 2 ]);
396410
});
397411

398412

@@ -414,8 +428,8 @@ describe('bp', function() {
414428
describe('.generateReportPartial()', function() {
415429
it('should return an html string with provided values', function() {
416430
bp.runState.numSamples = 9;
417-
expect(bp.generateReportPartial('foo', 10, [9,11])).
418-
toBe('<tr><td>foo</td><td class="average">10ms</td><td>[9, 11]ms</td></tr>')
431+
expect(bp.generateReportPartial('foo', {time: 10, gcTime: 5}, ['9', '11'], ['4','6'])).
432+
toBe('<tr><td>foo</td><td class="average">test:10ms<br>gc:5ms<br>combined: 15ms</td><td>9<br>11</td><td>4<br>6</td></tr>')
419433
});
420434
});
421435

benchmark/web/tree.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@
4343
<tr>
4444
<th>step</th>
4545
<th>average</th>
46-
<th>samples</th>
46+
<th>test time (ms)</th>
47+
<th>gc time (ms)</th>
4748
</tr>
4849
</thead>
4950
<tbody class="info" style="font-family: monospace"></tbody>

0 commit comments

Comments
 (0)