diff --git a/modules/benchpress/src/webdriver/chrome_driver_extension.ts b/modules/benchpress/src/webdriver/chrome_driver_extension.ts index a8c6c80159..0c355e579b 100644 --- a/modules/benchpress/src/webdriver/chrome_driver_extension.ts +++ b/modules/benchpress/src/webdriver/chrome_driver_extension.ts @@ -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>, - normalizedEvents: Array> = null) { + private _convertPerfRecordsToEvents(chromeEvents: Array>, + normalizedEvents: Array> = 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): 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, data: StringMap new ChromeDriverExtension(driver), [WebDriverAdapter]) + .toFactory((driver, userAgent) => new ChromeDriverExtension(driver, userAgent), + [WebDriverAdapter, Options.USER_AGENT]) ]; diff --git a/modules/benchpress/test/webdriver/chrome_driver_extension_spec.ts b/modules/benchpress/test/webdriver/chrome_driver_extension_spec.ts index d20ef5069f..2ba436b5d8 100644 --- a/modules/benchpress/test/webdriver/chrome_driver_extension_spec.ts +++ b/modules/benchpress/test/webdriver/chrome_driver_extension_spec.ts @@ -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; }) diff --git a/protractor-shared.js b/protractor-shared.js index 0868529772..d872768639 100644 --- a/protractor-shared.js +++ b/protractor-shared.js @@ -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' } };