Skip to content
This repository was archived by the owner on Dec 4, 2017. It is now read-only.

Commit fe1dd77

Browse files
Olivier Chafikochafik
Olivier Chafik
authored andcommitted
feat(benchpress): add receivedData + requestCount to PerflogMetric
Closes #5750
1 parent 24dcd26 commit fe1dd77

File tree

7 files changed

+234
-51
lines changed

7 files changed

+234
-51
lines changed

modules/benchpress/docs/index.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,20 @@ In addition to that, one extra binding needs to be passed to benchpress in tests
175175

176176
benchpress.sample(bindings: [bp.bind(bp.Options.CAPTURE_FRAMES).toValue(true)], ... )
177177

178+
# Requests Metrics
179+
180+
Benchpress can also record the number of requests sent and count the received "encoded" bytes since [window.performance.timing.navigationStart](http://www.w3.org/TR/navigation-timing/#dom-performancetiming-navigationstart):
181+
182+
- `receivedData`: number of bytes received since the last navigation start
183+
- `requestCount`: number of requests sent since the last navigation start
184+
185+
To collect these metrics, you need the following corresponding extra bindings:
186+
187+
benchpress.sample(bindings: [
188+
bp.bind(bp.Options.RECEIVED_DATA).toValue(true),
189+
bp.bind(bp.Options.REQUEST_COUNT).toValue(true)
190+
], ... )
191+
178192
# Best practices
179193

180194
* Use normalized environments

modules/benchpress/src/common_options.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ export class Options {
2626
// TODO(tbosch): use static values when our transpiler supports them
2727
static get MICRO_METRICS() { return _MICRO_METRICS; }
2828
// TODO(tbosch): use static values when our transpiler supports them
29+
static get RECEIVED_DATA() { return _RECEIVED_DATA; }
30+
// TODO(tbosch): use static values when our transpiler supports them
31+
static get REQUEST_COUNT() { return _REQUEST_COUNT; }
32+
// TODO(tbosch): use static values when our transpiler supports them
2933
static get CAPTURE_FRAMES() { return _CAPTURE_FRAMES; }
3034
}
3135

@@ -40,6 +44,8 @@ var _USER_AGENT = new OpaqueToken('Options.userAgent');
4044
var _MICRO_METRICS = new OpaqueToken('Options.microMetrics');
4145
var _NOW = new OpaqueToken('Options.now');
4246
var _WRITE_FILE = new OpaqueToken('Options.writeFile');
47+
var _RECEIVED_DATA = new OpaqueToken('Options.receivedData');
48+
var _REQUEST_COUNT = new OpaqueToken('Options.requestCount');
4349
var _CAPTURE_FRAMES = new OpaqueToken('Options.frameCapture');
4450

4551
var _DEFAULT_PROVIDERS = [
@@ -50,5 +56,7 @@ var _DEFAULT_PROVIDERS = [
5056
provide(_PREPARE, {useValue: false}),
5157
provide(_MICRO_METRICS, {useValue: {}}),
5258
provide(_NOW, {useValue: () => DateWrapper.now()}),
59+
provide(_RECEIVED_DATA, {useValue: false}),
60+
provide(_REQUEST_COUNT, {useValue: false}),
5361
provide(_CAPTURE_FRAMES, {useValue: false})
5462
];

modules/benchpress/src/metric/perflog_metric.ts

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,18 @@ export class PerflogMetric extends Metric {
3636
**/
3737
constructor(private _driverExtension: WebDriverExtension, private _setTimeout: Function,
3838
private _microMetrics: {[key: string]: any}, private _forceGc: boolean,
39-
private _captureFrames: boolean) {
39+
private _captureFrames: boolean, private _receivedData: boolean,
40+
private _requestCount: boolean) {
4041
super();
4142

4243
this._remainingEvents = [];
4344
this._measureCount = 0;
4445
this._perfLogFeatures = _driverExtension.perfLogFeatures();
46+
if (!this._perfLogFeatures.userTiming) {
47+
// User timing is needed for navigationStart.
48+
this._receivedData = false;
49+
this._requestCount = false;
50+
}
4551
}
4652

4753
describe(): {[key: string]: any} {
@@ -61,6 +67,12 @@ export class PerflogMetric extends Metric {
6167
res['forcedGcAmount'] = 'forced gc amount in kbytes';
6268
}
6369
}
70+
if (this._receivedData) {
71+
res['receivedData'] = 'encoded bytes received since navigationStart';
72+
}
73+
if (this._requestCount) {
74+
res['requestCount'] = 'count of requests sent since navigationStart';
75+
}
6476
if (this._captureFrames) {
6577
if (!this._perfLogFeatures.frameCapture) {
6678
var warningMsg = 'WARNING: Metric requested, but not supported by driver';
@@ -188,6 +200,12 @@ export class PerflogMetric extends Metric {
188200
result['frameTime.smooth'] = 0;
189201
}
190202
StringMapWrapper.forEach(this._microMetrics, (desc, name) => { result[name] = 0; });
203+
if (this._receivedData) {
204+
result['receivedData'] = 0;
205+
}
206+
if (this._requestCount) {
207+
result['requestCount'] = 0;
208+
}
191209

192210
var markStartEvent = null;
193211
var markEndEvent = null;
@@ -217,6 +235,22 @@ export class PerflogMetric extends Metric {
217235
markEndEvent = event;
218236
}
219237

238+
let isInstant = StringWrapper.equals(ph, 'I') || StringWrapper.equals(ph, 'i');
239+
if (this._requestCount && StringWrapper.equals(name, 'sendRequest')) {
240+
result['requestCount'] += 1;
241+
} else if (this._receivedData && StringWrapper.equals(name, 'receivedData') && isInstant) {
242+
result['receivedData'] += event['args']['encodedDataLength'];
243+
} else if (StringWrapper.equals(name, 'navigationStart')) {
244+
// We count data + requests since the last navigationStart
245+
// (there might be chrome extensions loaded by selenium before our page, so there
246+
// will likely be more than one navigationStart).
247+
if (this._receivedData) {
248+
result['receivedData'] = 0;
249+
}
250+
if (this._requestCount) {
251+
result['requestCount'] = 0;
252+
}
253+
}
220254
if (isPresent(markStartEvent) && isBlank(markEndEvent) &&
221255
event['pid'] === markStartEvent['pid']) {
222256
if (StringWrapper.equals(ph, 'b') && StringWrapper.equals(name, _MARK_NAME_FRAME_CAPUTRE)) {
@@ -236,7 +270,7 @@ export class PerflogMetric extends Metric {
236270
frameCaptureEndEvent = event;
237271
}
238272

239-
if (StringWrapper.equals(ph, 'I') || StringWrapper.equals(ph, 'i')) {
273+
if (isInstant) {
240274
if (isPresent(frameCaptureStartEvent) && isBlank(frameCaptureEndEvent) &&
241275
StringWrapper.equals(name, 'frame')) {
242276
frameTimestamps.push(event['ts']);
@@ -332,14 +366,17 @@ var _FRAME_TIME_SMOOTH_THRESHOLD = 17;
332366
var _PROVIDERS = [
333367
bind(PerflogMetric)
334368
.toFactory(
335-
(driverExtension, setTimeout, microMetrics, forceGc, captureFrames) =>
336-
new PerflogMetric(driverExtension, setTimeout, microMetrics, forceGc, captureFrames),
369+
(driverExtension, setTimeout, microMetrics, forceGc, captureFrames, receivedData,
370+
requestCount) => new PerflogMetric(driverExtension, setTimeout, microMetrics, forceGc,
371+
captureFrames, receivedData, requestCount),
337372
[
338373
WebDriverExtension,
339374
_SET_TIMEOUT,
340375
Options.MICRO_METRICS,
341376
Options.FORCE_GC,
342-
Options.CAPTURE_FRAMES
377+
Options.CAPTURE_FRAMES,
378+
Options.RECEIVED_DATA,
379+
Options.REQUEST_COUNT
343380
]),
344381
provide(_SET_TIMEOUT, {useValue: (fn, millis) => TimerWrapper.setTimeout(fn, millis)})
345382
];

modules/benchpress/src/web_driver_extension.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,15 @@ export class PerfLogFeatures {
6666
render: boolean;
6767
gc: boolean;
6868
frameCapture: boolean;
69+
userTiming: boolean;
6970

70-
constructor({render = false, gc = false, frameCapture = false}:
71-
{render?: boolean, gc?: boolean, frameCapture?: boolean} = {}) {
71+
constructor(
72+
{render = false, gc = false, frameCapture = false, userTiming = false}:
73+
{render?: boolean, gc?: boolean, frameCapture?: boolean, userTiming?: boolean} = {}) {
7274
this.render = render;
7375
this.gc = gc;
7476
this.frameCapture = frameCapture;
77+
this.userTiming = userTiming;
7578
}
7679
}
7780

modules/benchpress/src/webdriver/chrome_driver_extension.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,15 @@ export class ChromeDriverExtension extends WebDriverExtension {
193193
this._isEvent(categories, name, ['devtools.timeline'], 'Layout') ||
194194
this._isEvent(categories, name, ['devtools.timeline'], 'Paint')) {
195195
return normalizeEvent(event, {'name': 'render'});
196+
} else if (this._isEvent(categories, name, ['devtools.timeline'], 'ResourceReceivedData')) {
197+
let normArgs = {'encodedDataLength': args['data']['encodedDataLength']};
198+
return normalizeEvent(event, {'name': 'receivedData', 'args': normArgs});
199+
} else if (this._isEvent(categories, name, ['devtools.timeline'], 'ResourceSendRequest')) {
200+
let data = args['data'];
201+
let normArgs = {'url': data['url'], 'method': data['requestMethod']};
202+
return normalizeEvent(event, {'name': 'sendRequest', 'args': normArgs});
203+
} else if (this._isEvent(categories, name, ['blink.user_timing'], 'navigationStart')) {
204+
return normalizeEvent(event, {'name': name});
196205
}
197206
return null; // nothing useful in this event
198207
}
@@ -208,7 +217,7 @@ export class ChromeDriverExtension extends WebDriverExtension {
208217
}
209218

210219
perfLogFeatures(): PerfLogFeatures {
211-
return new PerfLogFeatures({render: true, gc: true, frameCapture: true});
220+
return new PerfLogFeatures({render: true, gc: true, frameCapture: true, userTiming: true});
212221
}
213222

214223
supports(capabilities: {[key: string]: any}): boolean {

0 commit comments

Comments
 (0)