Skip to content

Commit 146d731

Browse files
committed
feat(bench press): detect major gcs
1 parent eb6385e commit 146d731

File tree

5 files changed

+84
-58
lines changed

5 files changed

+84
-58
lines changed

modules/benchpress/src/metric/perflog_metric.js

+15-9
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ export class PerflogMetric extends Metric {
4343
'render': 'render time in ms',
4444
'gcTime': 'gc time in ms',
4545
'gcAmount': 'gc amount in kbytes',
46-
'gcTimeInScript': 'gc time during script execution in ms',
47-
'gcAmountInScript': 'gc amount during script execution in kbytes'
46+
'majorGcTime': 'time of major gcs in ms',
47+
'majorGcAmount': 'amount of major gcs in kbytes'
4848
};
4949
if (this._microIterations > 0) {
5050
res['scriptMicroAvg'] = 'average script time for a micro iteration';
@@ -124,12 +124,13 @@ export class PerflogMetric extends Metric {
124124
'render': 0,
125125
'gcTime': 0,
126126
'gcAmount': 0,
127-
'gcTimeInScript': 0,
128-
'gcAmountInScript': 0
127+
'majorGcTime': 0,
128+
'majorGcAmount': 0
129129
};
130130

131131
var markStartEvent = null;
132132
var markEndEvent = null;
133+
var gcTimeInScript = 0;
133134

134135
var intervalStarts = {};
135136
events.forEach( (event) => {
@@ -148,19 +149,24 @@ export class PerflogMetric extends Metric {
148149
var duration = event['ts'] - startEvent['ts'];
149150
intervalStarts[name] = null;
150151
if (StringWrapper.equals(name, 'gc')) {
152+
var amount = (startEvent['args']['usedHeapSize'] - event['args']['usedHeapSize']) / 1000;
151153
result['gcTime'] += duration;
152-
result['gcAmount'] += (startEvent['args']['usedHeapSize'] - event['args']['usedHeapSize']) / 1000;
154+
result['gcAmount'] += amount;
155+
var majorGc = event['args']['majorGc'];
156+
if (isPresent(majorGc) && majorGc) {
157+
result['majorGcTime'] += duration;
158+
result['majorGcAmount'] += amount;
159+
}
153160
if (isPresent(intervalStarts['script'])) {
154-
result['gcTimeInScript'] += duration;
155-
result['gcAmountInScript'] += result['gcAmount'];
161+
gcTimeInScript += duration;
156162
}
157-
} else {
163+
} else if (StringWrapper.equals(name, 'script') || StringWrapper.equals(name, 'render')) {
158164
result[name] += duration;
159165
}
160166
}
161167
}
162168
});
163-
result['script'] -= result['gcTimeInScript'];
169+
result['script'] -= gcTimeInScript;
164170
if (this._microIterations > 0) {
165171
result['scriptMicroAvg'] = result['script'] / this._microIterations;
166172
}

modules/benchpress/src/webdriver/chrome_driver_extension.js

+17-3
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,13 @@ export class ChromeDriverExtension extends WebDriverExtension {
6161
if (isBlank(normalizedEvents)) {
6262
normalizedEvents = [];
6363
}
64+
var majorGCPids = {};
6465
chromeEvents.forEach( (event) => {
6566
var cat = event['cat'];
6667
var name = event['name'];
6768
var args = event['args'];
69+
var pid = event['pid'];
70+
var ph = event['ph'];
6871
if (StringWrapper.equals(cat, 'disabled-by-default-devtools.timeline')) {
6972
if (StringWrapper.equals(name, 'FunctionCall') &&
7073
(isBlank(args) || isBlank(args['data']) || !StringWrapper.equals(args['data']['scriptName'], 'InjectedScript'))) {
@@ -81,17 +84,28 @@ export class ChromeDriverExtension extends WebDriverExtension {
8184
'name': 'render'
8285
}));
8386
} else if (StringWrapper.equals(name, 'GCEvent')) {
87+
var normArgs = {
88+
'usedHeapSize': isPresent(args['usedHeapSizeAfter']) ? args['usedHeapSizeAfter'] : args['usedHeapSizeBefore']
89+
};
90+
if (StringWrapper.equals(event['ph'], 'E')) {
91+
normArgs['majorGc'] = isPresent(majorGCPids[pid]) && majorGCPids[pid];
92+
}
93+
majorGCPids[pid] = false;
8494
ListWrapper.push(normalizedEvents, normalizeEvent(event, {
8595
'name': 'gc',
86-
'args': {
87-
'usedHeapSize': isPresent(args['usedHeapSizeAfter']) ? args['usedHeapSizeAfter'] : args['usedHeapSizeBefore']
88-
}
96+
'args': normArgs
8997
}));
9098
}
9199
} else if (StringWrapper.equals(cat, 'blink.console')) {
92100
ListWrapper.push(normalizedEvents, normalizeEvent(event, {
93101
'name': name
94102
}));
103+
} else if (StringWrapper.equals(cat, 'v8')) {
104+
if (StringWrapper.equals(name, 'majorGC')) {
105+
if (StringWrapper.equals(ph, 'B')) {
106+
majorGCPids[pid] = true;
107+
}
108+
}
95109
}
96110
});
97111
return normalizedEvents;

modules/benchpress/test/metric/perflog_metric_spec.js

+18-44
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ export function main() {
221221
});
222222
});
223223

224-
['script', 'gcTime', 'render'].forEach( (metricName) => {
224+
['script', 'render'].forEach( (metricName) => {
225225
it(`should support ${metricName} metric`, (done) => {
226226
aggregate([
227227
eventFactory.start(metricName, 0),
@@ -233,12 +233,28 @@ export function main() {
233233
});
234234
});
235235

236-
it('should support gcAmount metric', (done) => {
236+
it('should support gcTime/gcAmount metric', (done) => {
237237
aggregate([
238238
eventFactory.start('gc', 0, {'usedHeapSize': 2500}),
239239
eventFactory.end('gc', 5, {'usedHeapSize': 1000})
240240
]).then((data) => {
241+
expect(data['gcTime']).toBe(5);
241242
expect(data['gcAmount']).toBe(1.5);
243+
expect(data['majorGcTime']).toBe(0);
244+
expect(data['majorGcAmount']).toBe(0);
245+
done();
246+
});
247+
});
248+
249+
it('should support majorGcTime/majorGcAmount metric', (done) => {
250+
aggregate([
251+
eventFactory.start('gc', 0, {'usedHeapSize': 2500}),
252+
eventFactory.end('gc', 5, {'usedHeapSize': 1000, 'majorGc': true})
253+
]).then((data) => {
254+
expect(data['gcTime']).toBe(5);
255+
expect(data['gcAmount']).toBe(1.5);
256+
expect(data['majorGcTime']).toBe(5);
257+
expect(data['majorGcAmount']).toBe(1.5);
242258
done();
243259
});
244260
});
@@ -280,48 +296,6 @@ export function main() {
280296

281297
});
282298

283-
describe('gcTimeInScript / gcAmountInScript', () => {
284-
285-
it('should detect gc during script execution with begin/end events', (done) => {
286-
aggregate([
287-
eventFactory.start('script', 0),
288-
eventFactory.start('gc', 1, {'usedHeapSize': 10000}),
289-
eventFactory.end('gc', 4, {'usedHeapSize': 0}),
290-
eventFactory.end('script', 5)
291-
]).then((data) => {
292-
expect(data['gcTimeInScript']).toBe(3);
293-
expect(data['gcAmountInScript']).toBe(10.0);
294-
done();
295-
});
296-
});
297-
298-
it('should detect gc during script execution with complete events', (done) => {
299-
aggregate([
300-
eventFactory.complete('script', 0, 5),
301-
eventFactory.start('gc', 1, {'usedHeapSize': 10000}),
302-
eventFactory.end('gc', 4, {'usedHeapSize': 0})
303-
]).then((data) => {
304-
expect(data['gcTimeInScript']).toBe(3);
305-
expect(data['gcAmountInScript']).toBe(10.0);
306-
done();
307-
});
308-
});
309-
310-
it('should ignore gc outside of script execution', (done) => {
311-
aggregate([
312-
eventFactory.start('gc', 1, {'usedHeapSize': 10}),
313-
eventFactory.end('gc', 4, {'usedHeapSize': 0}),
314-
eventFactory.start('script', 0),
315-
eventFactory.end('script', 5)
316-
]).then((data) => {
317-
expect(data['gcTimeInScript']).toEqual(0.0);
318-
expect(data['gcAmountInScript']).toEqual(0.0);
319-
done();
320-
});
321-
});
322-
323-
});
324-
325299
});
326300

327301
});

modules/benchpress/test/webdriver/chrome_driver_extension_spec.js

+33-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ export function main() {
1717
var extension;
1818

1919
var blinkEvents = new TraceEventFactory('blink.console', 'pid0');
20+
var v8Events = new TraceEventFactory('v8', 'pid0');
21+
var v8EventsOtherProcess = new TraceEventFactory('v8', 'pid1');
2022
var chromeTimelineEvents = new TraceEventFactory('disabled-by-default-devtools.timeline', 'pid0');
2123
var normEvents = new TraceEventFactory('timeline', 'pid0');
2224

@@ -143,7 +145,37 @@ export function main() {
143145
]).readPerfLog().then( (events) => {
144146
expect(events).toEqual([
145147
normEvents.start('gc', 1.0, {'usedHeapSize': 1000}),
146-
normEvents.end('gc', 2.0, {'usedHeapSize': 0}),
148+
normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': false}),
149+
]);
150+
done();
151+
});
152+
});
153+
154+
it('should report major gc', (done) => {
155+
createExtension([
156+
chromeTimelineEvents.start('GCEvent', 1000, {'usedHeapSizeBefore': 1000}),
157+
v8EventsOtherProcess.start('majorGC', 1100, null),
158+
v8EventsOtherProcess.end('majorGC', 1200, null),
159+
chromeTimelineEvents.end('GCEvent', 2000, {'usedHeapSizeAfter': 0}),
160+
]).readPerfLog().then( (events) => {
161+
expect(events).toEqual([
162+
normEvents.start('gc', 1.0, {'usedHeapSize': 1000}),
163+
normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': false}),
164+
]);
165+
done();
166+
});
167+
});
168+
169+
it('should ignore major gc from different processes', (done) => {
170+
createExtension([
171+
chromeTimelineEvents.start('GCEvent', 1000, {'usedHeapSizeBefore': 1000}),
172+
v8Events.start('majorGC', 1100, null),
173+
v8Events.end('majorGC', 1200, null),
174+
chromeTimelineEvents.end('GCEvent', 2000, {'usedHeapSizeAfter': 0}),
175+
]).readPerfLog().then( (events) => {
176+
expect(events).toEqual([
177+
normEvents.start('gc', 1.0, {'usedHeapSize': 1000}),
178+
normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': true}),
147179
]);
148180
done();
149181
});

protractor-shared.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ var browsers = argv['browsers'].split(',');
3535
var CHROME_OPTIONS = {
3636
'args': ['--js-flags=--expose-gc'],
3737
'perfLoggingPrefs': {
38-
'traceCategories': 'blink.console,disabled-by-default-devtools.timeline'
38+
'traceCategories': 'v8,blink.console,disabled-by-default-devtools.timeline'
3939
}
4040
};
4141

0 commit comments

Comments
 (0)