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 {WebDriverAdapter} from '../web_driver_adapter';
|
||||
import {Promise} from 'angular2/src/core/facade/async';
|
||||
import {Options} from '../common_options';
|
||||
|
||||
/**
|
||||
* 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'
|
||||
* to the list above.
|
||||
|
@ -25,7 +26,27 @@ export class ChromeDriverExtension extends WebDriverExtension {
|
|||
// TODO(tbosch): use static values when our transpiler supports them
|
||||
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()'); }
|
||||
|
||||
|
@ -63,54 +84,19 @@ export class ChromeDriverExtension extends WebDriverExtension {
|
|||
});
|
||||
}
|
||||
|
||||
_convertPerfRecordsToEvents(chromeEvents: Array<StringMap<string, any>>,
|
||||
normalizedEvents: Array<StringMap<string, any>> = null) {
|
||||
private _convertPerfRecordsToEvents(chromeEvents: Array<StringMap<string, any>>,
|
||||
normalizedEvents: Array<StringMap<string, any>> = null) {
|
||||
if (isBlank(normalizedEvents)) {
|
||||
normalizedEvents = [];
|
||||
}
|
||||
var majorGCPids = {};
|
||||
chromeEvents.forEach((event) => {
|
||||
var cat = event['cat'];
|
||||
var categories = this._parseCategories(event['cat']);
|
||||
var name = event['name'];
|
||||
var args = event['args'];
|
||||
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')) {
|
||||
if (this._isEvent(categories, name, ['blink.console'])) {
|
||||
normalizedEvents.push(normalizeEvent(event, {'name': name}));
|
||||
|
||||
} else if (StringWrapper.equals(cat, 'v8')) {
|
||||
if (StringWrapper.equals(name, 'majorGC')) {
|
||||
if (StringWrapper.equals(ph, 'B')) {
|
||||
majorGCPids[pid] = true;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (StringWrapper.equals(cat, 'benchmark')) {
|
||||
} else if (this._isEvent(categories, name, ['benchmark'],
|
||||
'BenchmarkInstrumentation::ImplThreadRenderingStats')) {
|
||||
// TODO(goderbauer): Instead of BenchmarkInstrumentation::ImplThreadRenderingStats the
|
||||
// following events should be used (if available) for more accurate measurments:
|
||||
// 1st choice: vsync_before - ground truth on Android
|
||||
|
@ -118,26 +104,118 @@ export class ChromeDriverExtension extends WebDriverExtension {
|
|||
// new surfaces framework (not broadly enabled yet)
|
||||
// 3rd choice: BenchmarkInstrumentation::ImplThreadRenderingStats - fallback event that is
|
||||
// allways available if something is rendered
|
||||
if (StringWrapper.equals(name, 'BenchmarkInstrumentation::ImplThreadRenderingStats')) {
|
||||
var frameCount = event['args']['data']['frame_count'];
|
||||
if (frameCount > 1) {
|
||||
throw new BaseException('multi-frame render stats not supported');
|
||||
}
|
||||
if (frameCount == 1) {
|
||||
normalizedEvents.push(normalizeEvent(event, {'name': 'frame'}));
|
||||
}
|
||||
var frameCount = event['args']['data']['frame_count'];
|
||||
if (frameCount > 1) {
|
||||
throw new BaseException('multi-frame render stats not supported');
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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 {
|
||||
return new PerfLogFeatures({render: true, gc: true, frameCapture: true});
|
||||
}
|
||||
|
||||
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 = [
|
||||
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,
|
||||
WebDriverAdapter,
|
||||
Injector,
|
||||
bind
|
||||
bind,
|
||||
Options
|
||||
} from 'benchpress/common';
|
||||
|
||||
import {TraceEventFactory} from '../trace_event_factory';
|
||||
|
||||
export function main() {
|
||||
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 extension;
|
||||
|
||||
|
@ -34,18 +40,26 @@ export function main() {
|
|||
var v8EventsOtherProcess = new TraceEventFactory('v8', 'pid1');
|
||||
var chromeTimelineEvents =
|
||||
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 normEvents = new TraceEventFactory('timeline', 'pid0');
|
||||
|
||||
function createExtension(perfRecords = null, messageMethod = 'Tracing.dataCollected') {
|
||||
function createExtension(perfRecords = null, userAgent = null,
|
||||
messageMethod = 'Tracing.dataCollected') {
|
||||
if (isBlank(perfRecords)) {
|
||||
perfRecords = [];
|
||||
}
|
||||
if (isBlank(userAgent)) {
|
||||
userAgent = CHROME44_USER_AGENT;
|
||||
}
|
||||
log = [];
|
||||
extension = Injector.resolveAndCreate([
|
||||
ChromeDriverExtension.BINDINGS,
|
||||
bind(WebDriverAdapter)
|
||||
.toValue(new MockDriverAdapter(log, perfRecords, messageMethod))
|
||||
.toValue(new MockDriverAdapter(log, perfRecords, messageMethod)),
|
||||
bind(Options.USER_AGENT).toValue(userAgent)
|
||||
])
|
||||
.get(ChromeDriverExtension);
|
||||
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',
|
||||
inject([AsyncTestCompleter], (async) => {
|
||||
|
@ -100,17 +358,25 @@ export function main() {
|
|||
});
|
||||
}));
|
||||
|
||||
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();
|
||||
});
|
||||
}));
|
||||
['Rasterize', 'CompositeLayers'].forEach((recordType) => {
|
||||
it(`should report ${recordType} as "render"`, inject([AsyncTestCompleter], (async) => {
|
||||
createExtension(
|
||||
[
|
||||
chromeTimelineEvents.start(recordType, 1234),
|
||||
chromeTimelineEvents.end(recordType, 2345)
|
||||
],
|
||||
CHROME45_USER_AGENT)
|
||||
.readPerfLog()
|
||||
.then((events) => {
|
||||
expect(events).toEqual([
|
||||
normEvents.start('render', 1.234),
|
||||
normEvents.end('render', 2.345),
|
||||
]);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
describe('frame metrics', () => {
|
||||
it('should report ImplThreadRenderingStats as frame event',
|
||||
inject([AsyncTestCompleter], (async) => {
|
||||
|
@ -153,42 +419,9 @@ export function main() {
|
|||
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) => {
|
||||
createExtension([blinkEvents.create('S', 'someName', 1000)])
|
||||
.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) => {
|
||||
PromiseWrapper.catchError(
|
||||
createExtension(
|
||||
[
|
||||
chromeTimelineEvents.start('FunctionCall', 1234),
|
||||
],
|
||||
'Tracing.bufferUsage')
|
||||
CHROME45_USER_AGENT, 'Tracing.bufferUsage')
|
||||
.readPerfLog(),
|
||||
(err) => {
|
||||
expect(() => { throw err; })
|
||||
|
|
|
@ -38,7 +38,7 @@ var browsers = argv['browsers'].split(',');
|
|||
var CHROME_OPTIONS = {
|
||||
'args': ['--js-flags=--expose-gc'],
|
||||
'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