@@ -35,7 +35,8 @@ export class PerflogMetric extends Metric {
35
35
* @param microMetrics Name and description of metrics provided via console.time / console.timeEnd
36
36
**/
37
37
constructor ( private _driverExtension : WebDriverExtension , private _setTimeout : Function ,
38
- private _microMetrics : StringMap < string , any > , private _forceGc : boolean ) {
38
+ private _microMetrics : StringMap < string , any > , private _forceGc : boolean ,
39
+ private _captureFrames : boolean ) {
39
40
super ( ) ;
40
41
41
42
this . _remainingEvents = [ ] ;
@@ -60,6 +61,11 @@ export class PerflogMetric extends Metric {
60
61
res [ 'forcedGcAmount' ] = 'forced gc amount in kbytes' ;
61
62
}
62
63
}
64
+ if ( this . _captureFrames ) {
65
+ res [ 'meanFrameTime' ] = this . _perfLogFeatures . frameCapture ?
66
+ 'mean frame time in ms (target: 16.6ms for 60fps)' :
67
+ 'WARNING: Metric requested, but not supported by driver' ;
68
+ }
63
69
StringMapWrapper . forEach ( this . _microMetrics ,
64
70
( desc , name ) => { StringMapWrapper . set ( res , name , desc ) ; } ) ;
65
71
return res ;
@@ -83,9 +89,13 @@ export class PerflogMetric extends Metric {
83
89
84
90
_endPlainMeasureAndMeasureForceGc ( restartMeasure : boolean ) {
85
91
return this . _endMeasure ( true ) . then ( ( measureValues ) => {
92
+ // disable frame capture for measurments during forced gc
93
+ var originalFrameCaptureValue = this . _captureFrames ;
94
+ this . _captureFrames = false ;
86
95
return this . _driverExtension . gc ( )
87
96
. then ( ( _ ) => this . _endMeasure ( restartMeasure ) )
88
97
. then ( ( forceGcMeasureValues ) => {
98
+ this . _captureFrames = originalFrameCaptureValue ;
89
99
StringMapWrapper . set ( measureValues , 'forcedGcTime' , forceGcMeasureValues [ 'gcTime' ] ) ;
90
100
StringMapWrapper . set ( measureValues , 'forcedGcAmount' , forceGcMeasureValues [ 'gcAmount' ] ) ;
91
101
return measureValues ;
@@ -161,13 +171,21 @@ export class PerflogMetric extends Metric {
161
171
if ( this . _perfLogFeatures . render ) {
162
172
result [ 'renderTime' ] = 0 ;
163
173
}
174
+ if ( this . _captureFrames ) {
175
+ result [ 'meanFrameTime' ] = 0 ;
176
+ }
164
177
StringMapWrapper . forEach ( this . _microMetrics , ( desc , name ) => { result [ name ] = 0 ; } ) ;
165
178
166
179
var markStartEvent = null ;
167
180
var markEndEvent = null ;
168
181
var gcTimeInScript = 0 ;
169
182
var renderTimeInScript = 0 ;
170
183
184
+ var frameTimestamps = [ ] ;
185
+ var frameTimes = [ ] ;
186
+ var frameCaptureStartEvent = null ;
187
+ var frameCaptureEndEvent = null ;
188
+
171
189
var intervalStarts : StringMap < string , any > = { } ;
172
190
var intervalStartCount : StringMap < string , number > = { } ;
173
191
events . forEach ( ( event ) => {
@@ -185,8 +203,37 @@ export class PerflogMetric extends Metric {
185
203
} else if ( StringWrapper . equals ( ph , 'e' ) && StringWrapper . equals ( name , markName ) ) {
186
204
markEndEvent = event ;
187
205
}
206
+
188
207
if ( isPresent ( markStartEvent ) && isBlank ( markEndEvent ) &&
189
208
event [ 'pid' ] === markStartEvent [ 'pid' ] ) {
209
+ if ( StringWrapper . equals ( ph , 'b' ) && StringWrapper . equals ( name , _MARK_NAME_FRAME_CAPUTRE ) ) {
210
+ if ( isPresent ( frameCaptureStartEvent ) ) {
211
+ throw new BaseException ( 'can capture frames only once per benchmark run' ) ;
212
+ }
213
+ if ( ! this . _captureFrames ) {
214
+ throw new BaseException (
215
+ 'found start event for frame capture, but frame capture was not requested in benchpress' )
216
+ }
217
+ frameCaptureStartEvent = event ;
218
+ } else if ( StringWrapper . equals ( ph , 'e' ) &&
219
+ StringWrapper . equals ( name , _MARK_NAME_FRAME_CAPUTRE ) ) {
220
+ if ( isBlank ( frameCaptureStartEvent ) ) {
221
+ throw new BaseException ( 'missing start event for frame capture' ) ;
222
+ }
223
+ frameCaptureEndEvent = event ;
224
+ }
225
+
226
+ if ( StringWrapper . equals ( ph , 'I' ) || StringWrapper . equals ( ph , 'i' ) ) {
227
+ if ( isPresent ( frameCaptureStartEvent ) && isBlank ( frameCaptureEndEvent ) &&
228
+ StringWrapper . equals ( name , 'frame' ) ) {
229
+ ListWrapper . push ( frameTimestamps , event [ 'ts' ] ) ;
230
+ if ( frameTimestamps . length >= 2 ) {
231
+ ListWrapper . push ( frameTimes , frameTimestamps [ frameTimestamps . length - 1 ] -
232
+ frameTimestamps [ frameTimestamps . length - 2 ] ) ;
233
+ }
234
+ }
235
+ }
236
+
190
237
if ( StringWrapper . equals ( ph , 'B' ) || StringWrapper . equals ( ph , 'b' ) ) {
191
238
if ( isBlank ( intervalStarts [ name ] ) ) {
192
239
intervalStartCount [ name ] = 1 ;
@@ -227,8 +274,25 @@ export class PerflogMetric extends Metric {
227
274
}
228
275
}
229
276
} ) ;
277
+ if ( ! isPresent ( markStartEvent ) || ! isPresent ( markEndEvent ) ) {
278
+ // not all events have been received, no further processing for now
279
+ return null ;
280
+ }
281
+
282
+ if ( isPresent ( markEndEvent ) && isPresent ( frameCaptureStartEvent ) &&
283
+ isBlank ( frameCaptureEndEvent ) ) {
284
+ throw new BaseException ( 'missing end event for frame capture' ) ;
285
+ }
286
+ if ( this . _captureFrames && isBlank ( frameCaptureStartEvent ) ) {
287
+ throw new BaseException (
288
+ 'frame capture requested in benchpress, but no start event was found' ) ;
289
+ }
290
+ if ( frameTimes . length > 0 ) {
291
+ result [ 'meanFrameTime' ] =
292
+ ListWrapper . reduce ( frameTimes , ( a , b ) => a + b , 0 ) / frameTimes . length ;
293
+ }
230
294
result [ 'pureScriptTime' ] = result [ 'scriptTime' ] - gcTimeInScript - renderTimeInScript ;
231
- return isPresent ( markStartEvent ) && isPresent ( markEndEvent ) ? result : null ;
295
+ return result ;
232
296
}
233
297
234
298
_markName ( index ) { return `${ _MARK_NAME_PREFIX } ${ index } ` ; }
@@ -239,10 +303,19 @@ var _MAX_RETRY_COUNT = 20;
239
303
var _MARK_NAME_PREFIX = 'benchpress' ;
240
304
var _SET_TIMEOUT = new OpaqueToken ( 'PerflogMetric.setTimeout' ) ;
241
305
306
+ var _MARK_NAME_FRAME_CAPUTRE = 'frameCapture' ;
307
+
242
308
var _BINDINGS = [
243
309
bind ( PerflogMetric )
244
- . toFactory ( ( driverExtension , setTimeout , microMetrics , forceGc ) =>
245
- new PerflogMetric ( driverExtension , setTimeout , microMetrics , forceGc ) ,
246
- [ WebDriverExtension , _SET_TIMEOUT , Options . MICRO_METRICS , Options . FORCE_GC ] ) ,
310
+ . toFactory (
311
+ ( driverExtension , setTimeout , microMetrics , forceGc , captureFrames ) =>
312
+ new PerflogMetric ( driverExtension , setTimeout , microMetrics , forceGc , captureFrames ) ,
313
+ [
314
+ WebDriverExtension ,
315
+ _SET_TIMEOUT ,
316
+ Options . MICRO_METRICS ,
317
+ Options . FORCE_GC ,
318
+ Options . CAPTURE_FRAMES
319
+ ] ) ,
247
320
bind ( _SET_TIMEOUT ) . toValue ( ( fn , millis ) => TimerWrapper . setTimeout ( fn , millis ) )
248
321
] ;
0 commit comments