Skip to content

Commit

Permalink
feat: optionally save complete performance log in chrome benchpress t…
Browse files Browse the repository at this point in the history
…ests

If RAW_PERFLOG_PATH is passed in as an option, benchpress saves chrome's
performance log to a json file. This allows developers to download the
json file and upload it to their browser to get a breakdown of chrome-side
resource usage during a test.
  • Loading branch information
treylitefm committed Jan 22, 2019
1 parent 50df897 commit 084171e
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 10 deletions.
4 changes: 3 additions & 1 deletion packages/benchpress/src/common_options.ts
Expand Up @@ -26,6 +26,7 @@ export class Options {
static RECEIVED_DATA = new InjectionToken('Options.receivedData');
static REQUEST_COUNT = new InjectionToken('Options.requestCount');
static CAPTURE_FRAMES = new InjectionToken('Options.frameCapture');
static RAW_PERFLOG_PATH = new InjectionToken('Options.rawPerflogPath');
static DEFAULT_PROVIDERS = [
{provide: Options.DEFAULT_DESCRIPTION, useValue: {}},
{provide: Options.SAMPLE_DESCRIPTION, useValue: {}},
Expand All @@ -36,7 +37,8 @@ export class Options {
{provide: Options.RECEIVED_DATA, useValue: false},
{provide: Options.REQUEST_COUNT, useValue: false},
{provide: Options.CAPTURE_FRAMES, useValue: false},
{provide: Options.WRITE_FILE, useValue: writeFile}
{provide: Options.WRITE_FILE, useValue: writeFile},
{provide: Options.RAW_PERFLOG_PATH, useValue: null}
];
}

Expand Down
25 changes: 17 additions & 8 deletions packages/benchpress/src/webdriver/chrome_driver_extension.ts
Expand Up @@ -7,6 +7,7 @@
*/

import {Inject, Injectable, StaticProvider} from '@angular/core';
import * as fs from 'fs';

import {Options} from '../common_options';
import {WebDriverAdapter} from '../web_driver_adapter';
Expand All @@ -23,15 +24,19 @@ import {PerfLogEvent, PerfLogFeatures, WebDriverExtension} from '../web_driver_e
export class ChromeDriverExtension extends WebDriverExtension {
static PROVIDERS = <StaticProvider>[{
provide: ChromeDriverExtension,
deps: [WebDriverAdapter, Options.USER_AGENT]
deps: [WebDriverAdapter, Options.USER_AGENT, Options.RAW_PERFLOG_PATH]
}];

private _majorChromeVersion: number;
private _firstRun = true;
private _rawPerflogPath: string;

constructor(private _driver: WebDriverAdapter, @Inject(Options.USER_AGENT) userAgent: string) {
constructor(
private driver: WebDriverAdapter, @Inject(Options.USER_AGENT) userAgent: string,
@Inject(Options.RAW_PERFLOG_PATH) rawPerflogPath: string|null) {
super();
this._majorChromeVersion = this._parseChromeVersion(userAgent);
this._rawPerflogPath = rawPerflogPath;
}

private _parseChromeVersion(userAgent: string): number {
Expand All @@ -49,33 +54,33 @@ export class ChromeDriverExtension extends WebDriverExtension {
return parseInt(v, 10);
}

gc() { return this._driver.executeScript('window.gc()'); }
gc() { return this.driver.executeScript('window.gc()'); }

async timeBegin(name: string): Promise<any> {
if (this._firstRun) {
this._firstRun = false;
// Before the first run, read out the existing performance logs
// so that the chrome buffer does not fill up.
await this._driver.logs('performance');
await this.driver.logs('performance');
}
return this._driver.executeScript(`performance.mark('${name}-bpstart');`);
return this.driver.executeScript(`performance.mark('${name}-bpstart');`);
}

timeEnd(name: string, restartName: string|null = null): Promise<any> {
let script = `performance.mark('${name}-bpend');`;
if (restartName) {
script += `performance.mark('${restartName}-bpstart');`;
}
return this._driver.executeScript(script);
return this.driver.executeScript(script);
}

// See [Chrome Trace Event
// Format](https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit)
readPerfLog(): Promise<PerfLogEvent[]> {
// TODO(tbosch): Chromedriver bug https://code.google.com/p/chromedriver/issues/detail?id=1098
// Need to execute at least one command so that the browser logs can be read out!
return this._driver.executeScript('1+1')
.then((_) => this._driver.logs('performance'))
return this.driver.executeScript('1+1')
.then((_) => this.driver.logs('performance'))
.then((entries) => {
const events: PerfLogEvent[] = [];
entries.forEach((entry: any) => {
Expand All @@ -87,6 +92,10 @@ export class ChromeDriverExtension extends WebDriverExtension {
throw new Error('The DevTools trace buffer filled during the test!');
}
});

if (this._rawPerflogPath && events.length) {
fs.appendFileSync(this._rawPerflogPath, JSON.stringify(events));
}
return this._convertPerfRecordsToEvents(events);
});
}
Expand Down
Expand Up @@ -47,7 +47,8 @@ import {TraceEventFactory} from '../trace_event_factory';
provide: WebDriverAdapter,
useValue: new MockDriverAdapter(log, perfRecords, messageMethod)
},
{provide: Options.USER_AGENT, useValue: userAgent}
{provide: Options.USER_AGENT, useValue: userAgent},
{provide: Options.RAW_PERFLOG_PATH, useValue: null}
])
.get(ChromeDriverExtension);
return extension;
Expand Down

0 comments on commit 084171e

Please sign in to comment.