feat(bench press): detect major gcs
This commit is contained in:
parent
eb6385e143
commit
146d731e73
|
@ -43,8 +43,8 @@ export class PerflogMetric extends Metric {
|
||||||
'render': 'render time in ms',
|
'render': 'render time in ms',
|
||||||
'gcTime': 'gc time in ms',
|
'gcTime': 'gc time in ms',
|
||||||
'gcAmount': 'gc amount in kbytes',
|
'gcAmount': 'gc amount in kbytes',
|
||||||
'gcTimeInScript': 'gc time during script execution in ms',
|
'majorGcTime': 'time of major gcs in ms',
|
||||||
'gcAmountInScript': 'gc amount during script execution in kbytes'
|
'majorGcAmount': 'amount of major gcs in kbytes'
|
||||||
};
|
};
|
||||||
if (this._microIterations > 0) {
|
if (this._microIterations > 0) {
|
||||||
res['scriptMicroAvg'] = 'average script time for a micro iteration';
|
res['scriptMicroAvg'] = 'average script time for a micro iteration';
|
||||||
|
@ -124,12 +124,13 @@ export class PerflogMetric extends Metric {
|
||||||
'render': 0,
|
'render': 0,
|
||||||
'gcTime': 0,
|
'gcTime': 0,
|
||||||
'gcAmount': 0,
|
'gcAmount': 0,
|
||||||
'gcTimeInScript': 0,
|
'majorGcTime': 0,
|
||||||
'gcAmountInScript': 0
|
'majorGcAmount': 0
|
||||||
};
|
};
|
||||||
|
|
||||||
var markStartEvent = null;
|
var markStartEvent = null;
|
||||||
var markEndEvent = null;
|
var markEndEvent = null;
|
||||||
|
var gcTimeInScript = 0;
|
||||||
|
|
||||||
var intervalStarts = {};
|
var intervalStarts = {};
|
||||||
events.forEach( (event) => {
|
events.forEach( (event) => {
|
||||||
|
@ -148,19 +149,24 @@ export class PerflogMetric extends Metric {
|
||||||
var duration = event['ts'] - startEvent['ts'];
|
var duration = event['ts'] - startEvent['ts'];
|
||||||
intervalStarts[name] = null;
|
intervalStarts[name] = null;
|
||||||
if (StringWrapper.equals(name, 'gc')) {
|
if (StringWrapper.equals(name, 'gc')) {
|
||||||
|
var amount = (startEvent['args']['usedHeapSize'] - event['args']['usedHeapSize']) / 1000;
|
||||||
result['gcTime'] += duration;
|
result['gcTime'] += duration;
|
||||||
result['gcAmount'] += (startEvent['args']['usedHeapSize'] - event['args']['usedHeapSize']) / 1000;
|
result['gcAmount'] += amount;
|
||||||
if (isPresent(intervalStarts['script'])) {
|
var majorGc = event['args']['majorGc'];
|
||||||
result['gcTimeInScript'] += duration;
|
if (isPresent(majorGc) && majorGc) {
|
||||||
result['gcAmountInScript'] += result['gcAmount'];
|
result['majorGcTime'] += duration;
|
||||||
|
result['majorGcAmount'] += amount;
|
||||||
}
|
}
|
||||||
} else {
|
if (isPresent(intervalStarts['script'])) {
|
||||||
|
gcTimeInScript += duration;
|
||||||
|
}
|
||||||
|
} else if (StringWrapper.equals(name, 'script') || StringWrapper.equals(name, 'render')) {
|
||||||
result[name] += duration;
|
result[name] += duration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
result['script'] -= result['gcTimeInScript'];
|
result['script'] -= gcTimeInScript;
|
||||||
if (this._microIterations > 0) {
|
if (this._microIterations > 0) {
|
||||||
result['scriptMicroAvg'] = result['script'] / this._microIterations;
|
result['scriptMicroAvg'] = result['script'] / this._microIterations;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,10 +61,13 @@ export class ChromeDriverExtension extends WebDriverExtension {
|
||||||
if (isBlank(normalizedEvents)) {
|
if (isBlank(normalizedEvents)) {
|
||||||
normalizedEvents = [];
|
normalizedEvents = [];
|
||||||
}
|
}
|
||||||
|
var majorGCPids = {};
|
||||||
chromeEvents.forEach( (event) => {
|
chromeEvents.forEach( (event) => {
|
||||||
var cat = event['cat'];
|
var cat = event['cat'];
|
||||||
var name = event['name'];
|
var name = event['name'];
|
||||||
var args = event['args'];
|
var args = event['args'];
|
||||||
|
var pid = event['pid'];
|
||||||
|
var ph = event['ph'];
|
||||||
if (StringWrapper.equals(cat, 'disabled-by-default-devtools.timeline')) {
|
if (StringWrapper.equals(cat, 'disabled-by-default-devtools.timeline')) {
|
||||||
if (StringWrapper.equals(name, 'FunctionCall') &&
|
if (StringWrapper.equals(name, 'FunctionCall') &&
|
||||||
(isBlank(args) || isBlank(args['data']) || !StringWrapper.equals(args['data']['scriptName'], 'InjectedScript'))) {
|
(isBlank(args) || isBlank(args['data']) || !StringWrapper.equals(args['data']['scriptName'], 'InjectedScript'))) {
|
||||||
|
@ -81,17 +84,28 @@ export class ChromeDriverExtension extends WebDriverExtension {
|
||||||
'name': 'render'
|
'name': 'render'
|
||||||
}));
|
}));
|
||||||
} else if (StringWrapper.equals(name, 'GCEvent')) {
|
} else if (StringWrapper.equals(name, 'GCEvent')) {
|
||||||
|
var normArgs = {
|
||||||
|
'usedHeapSize': isPresent(args['usedHeapSizeAfter']) ? args['usedHeapSizeAfter'] : args['usedHeapSizeBefore']
|
||||||
|
};
|
||||||
|
if (StringWrapper.equals(event['ph'], 'E')) {
|
||||||
|
normArgs['majorGc'] = isPresent(majorGCPids[pid]) && majorGCPids[pid];
|
||||||
|
}
|
||||||
|
majorGCPids[pid] = false;
|
||||||
ListWrapper.push(normalizedEvents, normalizeEvent(event, {
|
ListWrapper.push(normalizedEvents, normalizeEvent(event, {
|
||||||
'name': 'gc',
|
'name': 'gc',
|
||||||
'args': {
|
'args': normArgs
|
||||||
'usedHeapSize': isPresent(args['usedHeapSizeAfter']) ? args['usedHeapSizeAfter'] : args['usedHeapSizeBefore']
|
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
} else if (StringWrapper.equals(cat, 'blink.console')) {
|
} else if (StringWrapper.equals(cat, 'blink.console')) {
|
||||||
ListWrapper.push(normalizedEvents, normalizeEvent(event, {
|
ListWrapper.push(normalizedEvents, normalizeEvent(event, {
|
||||||
'name': name
|
'name': name
|
||||||
}));
|
}));
|
||||||
|
} else if (StringWrapper.equals(cat, 'v8')) {
|
||||||
|
if (StringWrapper.equals(name, 'majorGC')) {
|
||||||
|
if (StringWrapper.equals(ph, 'B')) {
|
||||||
|
majorGCPids[pid] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return normalizedEvents;
|
return normalizedEvents;
|
||||||
|
|
|
@ -221,7 +221,7 @@ export function main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
['script', 'gcTime', 'render'].forEach( (metricName) => {
|
['script', 'render'].forEach( (metricName) => {
|
||||||
it(`should support ${metricName} metric`, (done) => {
|
it(`should support ${metricName} metric`, (done) => {
|
||||||
aggregate([
|
aggregate([
|
||||||
eventFactory.start(metricName, 0),
|
eventFactory.start(metricName, 0),
|
||||||
|
@ -233,12 +233,28 @@ export function main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support gcAmount metric', (done) => {
|
it('should support gcTime/gcAmount metric', (done) => {
|
||||||
aggregate([
|
aggregate([
|
||||||
eventFactory.start('gc', 0, {'usedHeapSize': 2500}),
|
eventFactory.start('gc', 0, {'usedHeapSize': 2500}),
|
||||||
eventFactory.end('gc', 5, {'usedHeapSize': 1000})
|
eventFactory.end('gc', 5, {'usedHeapSize': 1000})
|
||||||
]).then((data) => {
|
]).then((data) => {
|
||||||
|
expect(data['gcTime']).toBe(5);
|
||||||
expect(data['gcAmount']).toBe(1.5);
|
expect(data['gcAmount']).toBe(1.5);
|
||||||
|
expect(data['majorGcTime']).toBe(0);
|
||||||
|
expect(data['majorGcAmount']).toBe(0);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support majorGcTime/majorGcAmount metric', (done) => {
|
||||||
|
aggregate([
|
||||||
|
eventFactory.start('gc', 0, {'usedHeapSize': 2500}),
|
||||||
|
eventFactory.end('gc', 5, {'usedHeapSize': 1000, 'majorGc': true})
|
||||||
|
]).then((data) => {
|
||||||
|
expect(data['gcTime']).toBe(5);
|
||||||
|
expect(data['gcAmount']).toBe(1.5);
|
||||||
|
expect(data['majorGcTime']).toBe(5);
|
||||||
|
expect(data['majorGcAmount']).toBe(1.5);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -280,48 +296,6 @@ export function main() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('gcTimeInScript / gcAmountInScript', () => {
|
|
||||||
|
|
||||||
it('should detect gc during script execution with begin/end events', (done) => {
|
|
||||||
aggregate([
|
|
||||||
eventFactory.start('script', 0),
|
|
||||||
eventFactory.start('gc', 1, {'usedHeapSize': 10000}),
|
|
||||||
eventFactory.end('gc', 4, {'usedHeapSize': 0}),
|
|
||||||
eventFactory.end('script', 5)
|
|
||||||
]).then((data) => {
|
|
||||||
expect(data['gcTimeInScript']).toBe(3);
|
|
||||||
expect(data['gcAmountInScript']).toBe(10.0);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should detect gc during script execution with complete events', (done) => {
|
|
||||||
aggregate([
|
|
||||||
eventFactory.complete('script', 0, 5),
|
|
||||||
eventFactory.start('gc', 1, {'usedHeapSize': 10000}),
|
|
||||||
eventFactory.end('gc', 4, {'usedHeapSize': 0})
|
|
||||||
]).then((data) => {
|
|
||||||
expect(data['gcTimeInScript']).toBe(3);
|
|
||||||
expect(data['gcAmountInScript']).toBe(10.0);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should ignore gc outside of script execution', (done) => {
|
|
||||||
aggregate([
|
|
||||||
eventFactory.start('gc', 1, {'usedHeapSize': 10}),
|
|
||||||
eventFactory.end('gc', 4, {'usedHeapSize': 0}),
|
|
||||||
eventFactory.start('script', 0),
|
|
||||||
eventFactory.end('script', 5)
|
|
||||||
]).then((data) => {
|
|
||||||
expect(data['gcTimeInScript']).toEqual(0.0);
|
|
||||||
expect(data['gcAmountInScript']).toEqual(0.0);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,6 +17,8 @@ export function main() {
|
||||||
var extension;
|
var extension;
|
||||||
|
|
||||||
var blinkEvents = new TraceEventFactory('blink.console', 'pid0');
|
var blinkEvents = new TraceEventFactory('blink.console', 'pid0');
|
||||||
|
var v8Events = new TraceEventFactory('v8', 'pid0');
|
||||||
|
var v8EventsOtherProcess = new TraceEventFactory('v8', 'pid1');
|
||||||
var chromeTimelineEvents = new TraceEventFactory('disabled-by-default-devtools.timeline', 'pid0');
|
var chromeTimelineEvents = new TraceEventFactory('disabled-by-default-devtools.timeline', 'pid0');
|
||||||
var normEvents = new TraceEventFactory('timeline', 'pid0');
|
var normEvents = new TraceEventFactory('timeline', 'pid0');
|
||||||
|
|
||||||
|
@ -143,7 +145,37 @@ export function main() {
|
||||||
]).readPerfLog().then( (events) => {
|
]).readPerfLog().then( (events) => {
|
||||||
expect(events).toEqual([
|
expect(events).toEqual([
|
||||||
normEvents.start('gc', 1.0, {'usedHeapSize': 1000}),
|
normEvents.start('gc', 1.0, {'usedHeapSize': 1000}),
|
||||||
normEvents.end('gc', 2.0, {'usedHeapSize': 0}),
|
normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': false}),
|
||||||
|
]);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should report major gc', (done) => {
|
||||||
|
createExtension([
|
||||||
|
chromeTimelineEvents.start('GCEvent', 1000, {'usedHeapSizeBefore': 1000}),
|
||||||
|
v8EventsOtherProcess.start('majorGC', 1100, null),
|
||||||
|
v8EventsOtherProcess.end('majorGC', 1200, null),
|
||||||
|
chromeTimelineEvents.end('GCEvent', 2000, {'usedHeapSizeAfter': 0}),
|
||||||
|
]).readPerfLog().then( (events) => {
|
||||||
|
expect(events).toEqual([
|
||||||
|
normEvents.start('gc', 1.0, {'usedHeapSize': 1000}),
|
||||||
|
normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': false}),
|
||||||
|
]);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should ignore major gc from different processes', (done) => {
|
||||||
|
createExtension([
|
||||||
|
chromeTimelineEvents.start('GCEvent', 1000, {'usedHeapSizeBefore': 1000}),
|
||||||
|
v8Events.start('majorGC', 1100, null),
|
||||||
|
v8Events.end('majorGC', 1200, null),
|
||||||
|
chromeTimelineEvents.end('GCEvent', 2000, {'usedHeapSizeAfter': 0}),
|
||||||
|
]).readPerfLog().then( (events) => {
|
||||||
|
expect(events).toEqual([
|
||||||
|
normEvents.start('gc', 1.0, {'usedHeapSize': 1000}),
|
||||||
|
normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': true}),
|
||||||
]);
|
]);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
|
@ -35,7 +35,7 @@ var browsers = argv['browsers'].split(',');
|
||||||
var CHROME_OPTIONS = {
|
var CHROME_OPTIONS = {
|
||||||
'args': ['--js-flags=--expose-gc'],
|
'args': ['--js-flags=--expose-gc'],
|
||||||
'perfLoggingPrefs': {
|
'perfLoggingPrefs': {
|
||||||
'traceCategories': 'blink.console,disabled-by-default-devtools.timeline'
|
'traceCategories': 'v8,blink.console,disabled-by-default-devtools.timeline'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue