fix(benchpress): make benchpress fit for chrome 45

Closes #3411

Closes #3982
This commit is contained in:
Michael Goderbauer 2015-09-03 11:48:24 -07:00 committed by Michael Goderbauer
parent d8c5ab232c
commit 67b9414268
3 changed files with 416 additions and 172 deletions

View File

@ -13,10 +13,11 @@ import {
import {WebDriverExtension, PerfLogFeatures} from '../web_driver_extension'; import {WebDriverExtension, PerfLogFeatures} from '../web_driver_extension';
import {WebDriverAdapter} from '../web_driver_adapter'; import {WebDriverAdapter} from '../web_driver_adapter';
import {Promise} from 'angular2/src/core/facade/async'; import {Promise} from 'angular2/src/core/facade/async';
import {Options} from '../common_options';
/** /**
* Set the following 'traceCategories' to collect metrics in Chrome: * Set the following 'traceCategories' to collect metrics in Chrome:
* 'v8,blink.console,disabled-by-default-devtools.timeline' * 'v8,blink.console,disabled-by-default-devtools.timeline,devtools.timeline'
* *
* In order to collect the frame rate related metrics, add 'benchmark' * In order to collect the frame rate related metrics, add 'benchmark'
* to the list above. * to the list above.
@ -25,7 +26,27 @@ export class ChromeDriverExtension extends WebDriverExtension {
// TODO(tbosch): use static values when our transpiler supports them // TODO(tbosch): use static values when our transpiler supports them
static get BINDINGS(): Binding[] { return _BINDINGS; } static get BINDINGS(): Binding[] { return _BINDINGS; }
constructor(private _driver: WebDriverAdapter) { super(); } private _majorChromeVersion: number;
constructor(private _driver: WebDriverAdapter, userAgent: string) {
super();
this._majorChromeVersion = this._parseChromeVersion(userAgent);
}
private _parseChromeVersion(userAgent: string): number {
if (isBlank(userAgent)) {
return -1;
}
var v = StringWrapper.split(userAgent, /Chrom(e|ium)\//g)[2];
if (isBlank(v)) {
return -1;
}
v = StringWrapper.split(v, /\./g)[0];
if (isBlank(v)) {
return -1;
}
return NumberWrapper.parseInt(v, 10);
}
gc() { return this._driver.executeScript('window.gc()'); } gc() { return this._driver.executeScript('window.gc()'); }
@ -63,54 +84,19 @@ export class ChromeDriverExtension extends WebDriverExtension {
}); });
} }
_convertPerfRecordsToEvents(chromeEvents: Array<StringMap<string, any>>, private _convertPerfRecordsToEvents(chromeEvents: Array<StringMap<string, any>>,
normalizedEvents: Array<StringMap<string, any>> = null) { normalizedEvents: Array<StringMap<string, any>> = null) {
if (isBlank(normalizedEvents)) { if (isBlank(normalizedEvents)) {
normalizedEvents = []; normalizedEvents = [];
} }
var majorGCPids = {}; var majorGCPids = {};
chromeEvents.forEach((event) => { chromeEvents.forEach((event) => {
var cat = event['cat']; var categories = this._parseCategories(event['cat']);
var name = event['name']; var name = event['name'];
var args = event['args']; if (this._isEvent(categories, name, ['blink.console'])) {
var pid = event['pid'];
var ph = event['ph'];
if (StringWrapper.equals(cat, 'disabled-by-default-devtools.timeline')) {
if (StringWrapper.equals(name, 'FunctionCall') &&
(isBlank(args) || isBlank(args['data']) ||
!StringWrapper.equals(args['data']['scriptName'], 'InjectedScript'))) {
normalizedEvents.push(normalizeEvent(event, {'name': 'script'}));
} else if (StringWrapper.equals(name, 'RecalculateStyles') ||
StringWrapper.equals(name, 'Layout') ||
StringWrapper.equals(name, 'UpdateLayerTree') ||
StringWrapper.equals(name, 'Paint') || StringWrapper.equals(name, 'Rasterize') ||
StringWrapper.equals(name, 'CompositeLayers')) {
normalizedEvents.push(normalizeEvent(event, {'name': 'render'}));
} 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;
normalizedEvents.push(normalizeEvent(event, {'name': 'gc', 'args': normArgs}));
}
} else if (StringWrapper.equals(cat, 'blink.console')) {
normalizedEvents.push(normalizeEvent(event, {'name': name})); normalizedEvents.push(normalizeEvent(event, {'name': name}));
} else if (this._isEvent(categories, name, ['benchmark'],
} else if (StringWrapper.equals(cat, 'v8')) { 'BenchmarkInstrumentation::ImplThreadRenderingStats')) {
if (StringWrapper.equals(name, 'majorGC')) {
if (StringWrapper.equals(ph, 'B')) {
majorGCPids[pid] = true;
}
}
} else if (StringWrapper.equals(cat, 'benchmark')) {
// TODO(goderbauer): Instead of BenchmarkInstrumentation::ImplThreadRenderingStats the // TODO(goderbauer): Instead of BenchmarkInstrumentation::ImplThreadRenderingStats the
// following events should be used (if available) for more accurate measurments: // following events should be used (if available) for more accurate measurments:
// 1st choice: vsync_before - ground truth on Android // 1st choice: vsync_before - ground truth on Android
@ -118,26 +104,118 @@ export class ChromeDriverExtension extends WebDriverExtension {
// new surfaces framework (not broadly enabled yet) // new surfaces framework (not broadly enabled yet)
// 3rd choice: BenchmarkInstrumentation::ImplThreadRenderingStats - fallback event that is // 3rd choice: BenchmarkInstrumentation::ImplThreadRenderingStats - fallback event that is
// allways available if something is rendered // allways available if something is rendered
if (StringWrapper.equals(name, 'BenchmarkInstrumentation::ImplThreadRenderingStats')) { var frameCount = event['args']['data']['frame_count'];
var frameCount = event['args']['data']['frame_count']; if (frameCount > 1) {
if (frameCount > 1) { throw new BaseException('multi-frame render stats not supported');
throw new BaseException('multi-frame render stats not supported');
}
if (frameCount == 1) {
normalizedEvents.push(normalizeEvent(event, {'name': 'frame'}));
}
} }
if (frameCount == 1) {
normalizedEvents.push(normalizeEvent(event, {'name': 'frame'}));
}
} else if (this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'],
'Rasterize') ||
this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'],
'CompositeLayers')) {
normalizedEvents.push(normalizeEvent(event, {'name': 'render'}));
} else if (this._majorChromeVersion < 45) {
var normalizedEvent = this._processAsPreChrome45Event(event, categories, majorGCPids);
if (normalizedEvent != null) normalizedEvents.push(normalizedEvent);
} else {
var normalizedEvent = this._processAsPostChrome44Event(event, categories);
if (normalizedEvent != null) normalizedEvents.push(normalizedEvent);
} }
}); });
return normalizedEvents; return normalizedEvents;
} }
private _processAsPreChrome45Event(event, categories, majorGCPids) {
var name = event['name'];
var args = event['args'];
var pid = event['pid'];
var ph = event['ph'];
if (this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'],
'FunctionCall') &&
(isBlank(args) || isBlank(args['data']) ||
!StringWrapper.equals(args['data']['scriptName'], 'InjectedScript'))) {
return normalizeEvent(event, {'name': 'script'});
} else if (this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'],
'RecalculateStyles') ||
this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'],
'Layout') ||
this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'],
'UpdateLayerTree') ||
this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'],
'Paint')) {
return normalizeEvent(event, {'name': 'render'});
} else if (this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'],
'GCEvent')) {
var normArgs = {
'usedHeapSize': isPresent(args['usedHeapSizeAfter']) ? args['usedHeapSizeAfter'] :
args['usedHeapSizeBefore']
};
if (StringWrapper.equals(ph, 'E')) {
normArgs['majorGc'] = isPresent(majorGCPids[pid]) && majorGCPids[pid];
}
majorGCPids[pid] = false;
return normalizeEvent(event, {'name': 'gc', 'args': normArgs});
} else if (this._isEvent(categories, name, ['v8'], 'majorGC') &&
StringWrapper.equals(ph, 'B')) {
majorGCPids[pid] = true;
}
return null; // nothing useful in this event
}
private _processAsPostChrome44Event(event, categories) {
var name = event['name'];
var args = event['args'];
if (this._isEvent(categories, name, ['devtools.timeline', 'v8'], 'MajorGC')) {
var normArgs = {
'majorGc': true,
'usedHeapSize': isPresent(args['usedHeapSizeAfter']) ? args['usedHeapSizeAfter'] :
args['usedHeapSizeBefore']
};
return normalizeEvent(event, {'name': 'gc', 'args': normArgs});
} else if (this._isEvent(categories, name, ['devtools.timeline', 'v8'], 'MinorGC')) {
var normArgs = {
'majorGc': false,
'usedHeapSize': isPresent(args['usedHeapSizeAfter']) ? args['usedHeapSizeAfter'] :
args['usedHeapSizeBefore']
};
return normalizeEvent(event, {'name': 'gc', 'args': normArgs});
} else if (this._isEvent(categories, name, ['devtools.timeline', 'v8'], 'FunctionCall') &&
(isBlank(args) || isBlank(args['data']) ||
!StringWrapper.equals(args['data']['scriptName'], 'InjectedScript'))) {
return normalizeEvent(event, {'name': 'script'});
} else if (this._isEvent(categories, name, ['devtools.timeline', 'blink'],
'UpdateLayoutTree')) {
return normalizeEvent(event, {'name': 'render'});
} else if (this._isEvent(categories, name, ['devtools.timeline'], 'UpdateLayerTree') ||
this._isEvent(categories, name, ['devtools.timeline'], 'Layout') ||
this._isEvent(categories, name, ['devtools.timeline'], 'Paint')) {
return normalizeEvent(event, {'name': 'render'});
}
return null; // nothing useful in this event
}
private _parseCategories(categories: string): string[] {
return StringWrapper.split(categories, /,/g);
}
private _isEvent(eventCategories: string[], eventName: string, expectedCategories: string[],
expectedName: string = null): boolean {
var hasCategories = ListWrapper.reduce(expectedCategories, (value, cat) => {
return value && ListWrapper.contains(eventCategories, cat);
}, true);
return isBlank(expectedName) ? hasCategories :
hasCategories && StringWrapper.equals(eventName, expectedName);
}
perfLogFeatures(): PerfLogFeatures { perfLogFeatures(): PerfLogFeatures {
return new PerfLogFeatures({render: true, gc: true, frameCapture: true}); return new PerfLogFeatures({render: true, gc: true, frameCapture: true});
} }
supports(capabilities: StringMap<string, any>): boolean { supports(capabilities: StringMap<string, any>): boolean {
return StringWrapper.equals(capabilities['browserName'].toLowerCase(), 'chrome'); return this._majorChromeVersion != -1 &&
StringWrapper.equals(capabilities['browserName'].toLowerCase(), 'chrome');
} }
} }
@ -164,5 +242,6 @@ function normalizeEvent(chromeEvent: StringMap<string, any>, data: StringMap<str
var _BINDINGS = [ var _BINDINGS = [
bind(ChromeDriverExtension) bind(ChromeDriverExtension)
.toFactory((driver) => new ChromeDriverExtension(driver), [WebDriverAdapter]) .toFactory((driver, userAgent) => new ChromeDriverExtension(driver, userAgent),
[WebDriverAdapter, Options.USER_AGENT])
]; ];

View File

@ -19,13 +19,19 @@ import {
ChromeDriverExtension, ChromeDriverExtension,
WebDriverAdapter, WebDriverAdapter,
Injector, Injector,
bind bind,
Options
} from 'benchpress/common'; } from 'benchpress/common';
import {TraceEventFactory} from '../trace_event_factory'; import {TraceEventFactory} from '../trace_event_factory';
export function main() { export function main() {
describe('chrome driver extension', () => { describe('chrome driver extension', () => {
var CHROME44_USER_AGENT =
'"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.0 Safari/537.36"';
var CHROME45_USER_AGENT =
'"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2499.0 Safari/537.36"';
var log; var log;
var extension; var extension;
@ -34,18 +40,26 @@ export function main() {
var v8EventsOtherProcess = new TraceEventFactory('v8', 'pid1'); var v8EventsOtherProcess = new TraceEventFactory('v8', 'pid1');
var chromeTimelineEvents = var chromeTimelineEvents =
new TraceEventFactory('disabled-by-default-devtools.timeline', 'pid0'); new TraceEventFactory('disabled-by-default-devtools.timeline', 'pid0');
var chrome45TimelineEvents = new TraceEventFactory('devtools.timeline', 'pid0');
var chromeTimelineV8Events = new TraceEventFactory('devtools.timeline,v8', 'pid0');
var chromeBlinkTimelineEvents = new TraceEventFactory('blink,devtools.timeline', 'pid0');
var benchmarkEvents = new TraceEventFactory('benchmark', 'pid0'); var benchmarkEvents = new TraceEventFactory('benchmark', 'pid0');
var normEvents = new TraceEventFactory('timeline', 'pid0'); var normEvents = new TraceEventFactory('timeline', 'pid0');
function createExtension(perfRecords = null, messageMethod = 'Tracing.dataCollected') { function createExtension(perfRecords = null, userAgent = null,
messageMethod = 'Tracing.dataCollected') {
if (isBlank(perfRecords)) { if (isBlank(perfRecords)) {
perfRecords = []; perfRecords = [];
} }
if (isBlank(userAgent)) {
userAgent = CHROME44_USER_AGENT;
}
log = []; log = [];
extension = Injector.resolveAndCreate([ extension = Injector.resolveAndCreate([
ChromeDriverExtension.BINDINGS, ChromeDriverExtension.BINDINGS,
bind(WebDriverAdapter) bind(WebDriverAdapter)
.toValue(new MockDriverAdapter(log, perfRecords, messageMethod)) .toValue(new MockDriverAdapter(log, perfRecords, messageMethod)),
bind(Options.USER_AGENT).toValue(userAgent)
]) ])
.get(ChromeDriverExtension); .get(ChromeDriverExtension);
return extension; return extension;
@ -87,7 +101,251 @@ export function main() {
}); });
})); }));
describe('readPerfLog', () => { describe('readPerfLog Chrome44', () => {
it('should normalize times to ms and forward ph and pid event properties',
inject([AsyncTestCompleter], (async) => {
createExtension([chromeTimelineEvents.complete('FunctionCall', 1100, 5500, null)])
.readPerfLog()
.then((events) => {
expect(events).toEqual([
normEvents.complete('script', 1.1, 5.5, null),
]);
async.done();
});
}));
it('should normalize "tdur" to "dur"', inject([AsyncTestCompleter], (async) => {
var event = chromeTimelineEvents.create('X', 'FunctionCall', 1100, null);
event['tdur'] = 5500;
createExtension([event]).readPerfLog().then((events) => {
expect(events).toEqual([
normEvents.complete('script', 1.1, 5.5, null),
]);
async.done();
});
}));
it('should report FunctionCall events as "script"', inject([AsyncTestCompleter], (async) => {
createExtension([chromeTimelineEvents.start('FunctionCall', 0)])
.readPerfLog()
.then((events) => {
expect(events).toEqual([
normEvents.start('script', 0),
]);
async.done();
});
}));
it('should report gc', inject([AsyncTestCompleter], (async) => {
createExtension([
chromeTimelineEvents.start('GCEvent', 1000, {'usedHeapSizeBefore': 1000}),
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}),
]);
async.done();
});
}));
it('should ignore major gc from different processes',
inject([AsyncTestCompleter], (async) => {
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}),
]);
async.done();
});
}));
it('should report major gc', inject([AsyncTestCompleter], (async) => {
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}),
]);
async.done();
});
}));
['RecalculateStyles', 'Layout', 'UpdateLayerTree', 'Paint'].forEach((recordType) => {
it(`should report ${recordType} as "render"`, inject([AsyncTestCompleter], (async) => {
createExtension([
chromeTimelineEvents.start(recordType, 1234),
chromeTimelineEvents.end(recordType, 2345)
])
.readPerfLog()
.then((events) => {
expect(events).toEqual([
normEvents.start('render', 1.234),
normEvents.end('render', 2.345),
]);
async.done();
});
}));
});
it('should ignore FunctionCalls from webdriver', inject([AsyncTestCompleter], (async) => {
createExtension([
chromeTimelineEvents.start('FunctionCall', 0,
{'data': {'scriptName': 'InjectedScript'}})
])
.readPerfLog()
.then((events) => {
expect(events).toEqual([]);
async.done();
});
}));
});
describe('readPerfLog Chrome45', () => {
it('should normalize times to ms and forward ph and pid event properties',
inject([AsyncTestCompleter], (async) => {
createExtension([chromeTimelineV8Events.complete('FunctionCall', 1100, 5500, null)],
CHROME45_USER_AGENT)
.readPerfLog()
.then((events) => {
expect(events).toEqual([
normEvents.complete('script', 1.1, 5.5, null),
]);
async.done();
});
}));
it('should normalize "tdur" to "dur"', inject([AsyncTestCompleter], (async) => {
var event = chromeTimelineV8Events.create('X', 'FunctionCall', 1100, null);
event['tdur'] = 5500;
createExtension([event], CHROME45_USER_AGENT)
.readPerfLog()
.then((events) => {
expect(events).toEqual([
normEvents.complete('script', 1.1, 5.5, null),
]);
async.done();
});
}));
it('should report FunctionCall events as "script"', inject([AsyncTestCompleter], (async) => {
createExtension([chromeTimelineV8Events.start('FunctionCall', 0)], CHROME45_USER_AGENT)
.readPerfLog()
.then((events) => {
expect(events).toEqual([
normEvents.start('script', 0),
]);
async.done();
});
}));
it('should report minor gc', inject([AsyncTestCompleter], (async) => {
createExtension(
[
chromeTimelineV8Events.start('MinorGC', 1000, {'usedHeapSizeBefore': 1000}),
chromeTimelineV8Events.end('MinorGC', 2000, {'usedHeapSizeAfter': 0}),
],
CHROME45_USER_AGENT)
.readPerfLog()
.then((events) => {
expect(events.length).toEqual(2);
expect(events[0]).toEqual(
normEvents.start('gc', 1.0, {'usedHeapSize': 1000, 'majorGc': false}));
expect(events[1])
.toEqual(normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': false}));
async.done();
});
}));
it('should report major gc', inject([AsyncTestCompleter], (async) => {
createExtension(
[
chromeTimelineV8Events.start('MajorGC', 1000, {'usedHeapSizeBefore': 1000}),
chromeTimelineV8Events.end('MajorGC', 2000, {'usedHeapSizeAfter': 0}),
],
CHROME45_USER_AGENT)
.readPerfLog()
.then((events) => {
expect(events.length).toEqual(2);
expect(events[0])
.toEqual(normEvents.start('gc', 1.0, {'usedHeapSize': 1000, 'majorGc': true}));
expect(events[1])
.toEqual(normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': true}));
async.done();
});
}));
['Layout', 'UpdateLayerTree', 'Paint'].forEach((recordType) => {
it(`should report ${recordType} as "render"`, inject([AsyncTestCompleter], (async) => {
createExtension(
[
chrome45TimelineEvents.start(recordType, 1234),
chrome45TimelineEvents.end(recordType, 2345)
],
CHROME45_USER_AGENT)
.readPerfLog()
.then((events) => {
expect(events).toEqual([
normEvents.start('render', 1.234),
normEvents.end('render', 2.345),
]);
async.done();
});
}));
});
it(`should report UpdateLayoutTree as "render"`, inject([AsyncTestCompleter], (async) => {
createExtension(
[
chromeBlinkTimelineEvents.start('UpdateLayoutTree', 1234),
chromeBlinkTimelineEvents.end('UpdateLayoutTree', 2345)
],
CHROME45_USER_AGENT)
.readPerfLog()
.then((events) => {
expect(events).toEqual([
normEvents.start('render', 1.234),
normEvents.end('render', 2.345),
]);
async.done();
});
}));
it('should ignore FunctionCalls from webdriver', inject([AsyncTestCompleter], (async) => {
createExtension([
chromeTimelineV8Events.start('FunctionCall', 0,
{'data': {'scriptName': 'InjectedScript'}})
])
.readPerfLog()
.then((events) => {
expect(events).toEqual([]);
async.done();
});
}));
});
describe('readPerfLog (common)', () => {
it('should execute a dummy script before reading them', it('should execute a dummy script before reading them',
inject([AsyncTestCompleter], (async) => { inject([AsyncTestCompleter], (async) => {
@ -100,17 +358,25 @@ export function main() {
}); });
})); }));
it('should normalize times to ms and forward ph and pid event properties', ['Rasterize', 'CompositeLayers'].forEach((recordType) => {
inject([AsyncTestCompleter], (async) => { it(`should report ${recordType} as "render"`, inject([AsyncTestCompleter], (async) => {
createExtension([chromeTimelineEvents.complete('FunctionCall', 1100, 5500, null)]) createExtension(
.readPerfLog() [
.then((events) => { chromeTimelineEvents.start(recordType, 1234),
expect(events).toEqual([ chromeTimelineEvents.end(recordType, 2345)
normEvents.complete('script', 1.1, 5.5, null), ],
]); CHROME45_USER_AGENT)
async.done(); .readPerfLog()
}); .then((events) => {
})); expect(events).toEqual([
normEvents.start('render', 1.234),
normEvents.end('render', 2.345),
]);
async.done();
});
}));
});
describe('frame metrics', () => { describe('frame metrics', () => {
it('should report ImplThreadRenderingStats as frame event', it('should report ImplThreadRenderingStats as frame event',
inject([AsyncTestCompleter], (async) => { inject([AsyncTestCompleter], (async) => {
@ -153,42 +419,9 @@ export function main() {
async.done(); async.done();
}); });
})); }));
}); });
it('should normalize "tdur" to "dur"', inject([AsyncTestCompleter], (async) => {
var event = chromeTimelineEvents.create('X', 'FunctionCall', 1100, null);
event['tdur'] = 5500;
createExtension([event]).readPerfLog().then((events) => {
expect(events).toEqual([
normEvents.complete('script', 1.1, 5.5, null),
]);
async.done();
});
}));
it('should report FunctionCall events as "script"', inject([AsyncTestCompleter], (async) => {
createExtension([chromeTimelineEvents.start('FunctionCall', 0)])
.readPerfLog()
.then((events) => {
expect(events).toEqual([
normEvents.start('script', 0),
]);
async.done();
});
}));
it('should ignore FunctionCalls from webdriver', inject([AsyncTestCompleter], (async) => {
createExtension([
chromeTimelineEvents.start('FunctionCall', 0,
{'data': {'scriptName': 'InjectedScript'}})
])
.readPerfLog()
.then((events) => {
expect(events).toEqual([]);
async.done();
});
}));
it('should report begin timestamps', inject([AsyncTestCompleter], (async) => { it('should report begin timestamps', inject([AsyncTestCompleter], (async) => {
createExtension([blinkEvents.create('S', 'someName', 1000)]) createExtension([blinkEvents.create('S', 'someName', 1000)])
.readPerfLog() .readPerfLog()
@ -207,81 +440,13 @@ export function main() {
}); });
})); }));
it('should report gc', inject([AsyncTestCompleter], (async) => {
createExtension([
chromeTimelineEvents.start('GCEvent', 1000, {'usedHeapSizeBefore': 1000}),
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}),
]);
async.done();
});
}));
it('should report major gc', inject([AsyncTestCompleter], (async) => {
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}),
]);
async.done();
});
}));
it('should ignore major gc from different processes',
inject([AsyncTestCompleter], (async) => {
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}),
]);
async.done();
});
}));
['RecalculateStyles', 'Layout', 'UpdateLayerTree', 'Paint', 'Rasterize', 'CompositeLayers']
.forEach((recordType) => {
it(`should report ${recordType} as "render"`, inject([AsyncTestCompleter], (async) => {
createExtension([
chromeTimelineEvents.start(recordType, 1234),
chromeTimelineEvents.end(recordType, 2345)
])
.readPerfLog()
.then((events) => {
expect(events).toEqual([
normEvents.start('render', 1.234),
normEvents.end('render', 2.345),
]);
async.done();
});
}));
});
it('should throw an error on buffer overflow', inject([AsyncTestCompleter], (async) => { it('should throw an error on buffer overflow', inject([AsyncTestCompleter], (async) => {
PromiseWrapper.catchError( PromiseWrapper.catchError(
createExtension( createExtension(
[ [
chromeTimelineEvents.start('FunctionCall', 1234), chromeTimelineEvents.start('FunctionCall', 1234),
], ],
'Tracing.bufferUsage') CHROME45_USER_AGENT, 'Tracing.bufferUsage')
.readPerfLog(), .readPerfLog(),
(err) => { (err) => {
expect(() => { throw err; }) expect(() => { throw err; })

View File

@ -38,7 +38,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': 'v8,blink.console,disabled-by-default-devtools.timeline' 'traceCategories': 'v8,blink.console,disabled-by-default-devtools.timeline,devtools.timeline'
} }
}; };