fix(benchpress): make benchpress fit for chrome 45
Closes #3411 Closes #3982
This commit is contained in:
parent
d8c5ab232c
commit
67b9414268
|
@ -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])
|
||||||
];
|
];
|
||||||
|
|
|
@ -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; })
|
||||||
|
|
|
@ -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'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue