5
5
6
6
export namespace inputLatency {
7
7
8
- // Measurements are recorded in typed arrays with a fixed buffer length to their own impact on
9
- // input latency.
10
- const enum Constants {
11
- bufferLength = 256
12
- }
13
- const measurementsKeydown = new Float32Array ( Constants . bufferLength ) ;
14
- const measurementsInput = new Float32Array ( Constants . bufferLength ) ;
15
- const measurementsRender = new Float32Array ( Constants . bufferLength ) ;
16
- const measurementsInputLatency = new Float32Array ( Constants . bufferLength ) ;
8
+ // Measurements are recorded as totals, the average is calculated when the final measurements
9
+ // are created.
10
+ interface ICumulativeMeasurement {
11
+ total : number ;
12
+ min : number ;
13
+ max : number ;
14
+ }
15
+ const totalKeydownTime : ICumulativeMeasurement = { total : 0 , min : Number . MAX_VALUE , max : 0 } ;
16
+ const totalInputTime : ICumulativeMeasurement = { ...totalKeydownTime } ;
17
+ const totalRenderTime : ICumulativeMeasurement = { ...totalKeydownTime } ;
18
+ const totalInputLatencyTime : ICumulativeMeasurement = { ...totalKeydownTime } ;
17
19
let measurementsCount = 0 ;
18
20
21
+
22
+
19
23
// The state of each event, this helps ensure the integrity of the measurement and that
20
24
// something unexpected didn't happen that could skew the measurement.
21
25
const enum EventPhase {
@@ -107,10 +111,6 @@ export namespace inputLatency {
107
111
* Record the input latency sample if it's ready.
108
112
*/
109
113
function record ( ) {
110
- // Skip recording this frame if the buffer is full
111
- if ( measurementsCount >= Constants . bufferLength ) {
112
- return ;
113
- }
114
114
// Selection and render must have finished to record
115
115
if ( state . selection !== EventPhase . Finished || state . render !== EventPhase . Finished ) {
116
116
return ;
@@ -126,10 +126,10 @@ export namespace inputLatency {
126
126
performance . measure ( 'render' , 'render/start' , 'render/end' ) ;
127
127
performance . measure ( 'inputlatency' , 'inputlatency/start' , 'inputlatency/end' ) ;
128
128
129
- measurementsKeydown [ measurementsCount ] = performance . getEntriesByName ( 'keydown' ) [ 0 ] . duration ;
130
- measurementsInput [ measurementsCount ] = performance . getEntriesByName ( 'input' ) [ 0 ] . duration ;
131
- measurementsRender [ measurementsCount ] = performance . getEntriesByName ( 'render' ) [ 0 ] . duration ;
132
- measurementsInputLatency [ measurementsCount ] = performance . getEntriesByName ( 'inputlatency' ) [ 0 ] . duration ;
129
+ addMeasure ( 'keydown' , totalKeydownTime ) ;
130
+ addMeasure ( 'input' , totalInputTime ) ;
131
+ addMeasure ( 'render' , totalRenderTime ) ;
132
+ addMeasure ( 'inputlatency' , totalInputLatencyTime ) ;
133
133
134
134
// console.info(
135
135
// `input latency=${measurementsInputLatency[measurementsCount].toFixed(1)} [` +
@@ -146,6 +146,13 @@ export namespace inputLatency {
146
146
} , 0 ) ;
147
147
}
148
148
149
+ function addMeasure ( entryName : string , cumulativeMeasurement : ICumulativeMeasurement ) : void {
150
+ const duration = performance . getEntriesByName ( entryName ) [ 0 ] . duration ;
151
+ cumulativeMeasurement . total += duration ;
152
+ cumulativeMeasurement . min = Math . min ( cumulativeMeasurement . min , duration ) ;
153
+ cumulativeMeasurement . max = Math . max ( cumulativeMeasurement . max , duration ) ;
154
+ }
155
+
149
156
/**
150
157
* Clear the current sample.
151
158
*/
@@ -193,39 +200,37 @@ export namespace inputLatency {
193
200
return undefined ;
194
201
}
195
202
196
- // Calculate the average, min and max of each measurement
203
+ // Assemble the result
197
204
const result = {
198
- keydown : createSingleMeasurement ( ) ,
199
- input : createSingleMeasurement ( ) ,
200
- render : createSingleMeasurement ( ) ,
201
- total : createSingleMeasurement ( ) ,
205
+ keydown : cumulativeToFinalMeasurement ( totalKeydownTime ) ,
206
+ input : cumulativeToFinalMeasurement ( totalInputTime ) ,
207
+ render : cumulativeToFinalMeasurement ( totalRenderTime ) ,
208
+ total : cumulativeToFinalMeasurement ( totalInputLatencyTime ) ,
202
209
sampleCount : measurementsCount
203
210
} ;
204
- for ( let i = 0 ; i < result . sampleCount ; i ++ ) {
205
- result . keydown . average += measurementsKeydown [ i ] ;
206
- result . input . average += measurementsInput [ i ] ;
207
- result . render . average += measurementsRender [ i ] ;
208
- result . total . average += measurementsInputLatency [ i ] ;
209
- result . keydown . min = Math . min ( result . keydown . min , measurementsKeydown [ i ] ) ;
210
- result . input . min = Math . min ( result . input . min , measurementsInput [ i ] ) ;
211
- result . render . min = Math . min ( result . render . min , measurementsRender [ i ] ) ;
212
- result . total . min = Math . min ( result . total . min , measurementsInputLatency [ i ] ) ;
213
- result . keydown . max = Math . max ( result . keydown . max , measurementsKeydown [ i ] ) ;
214
- result . input . max = Math . max ( result . input . max , measurementsInput [ i ] ) ;
215
- result . render . max = Math . max ( result . render . max , measurementsRender [ i ] ) ;
216
- result . total . max = Math . max ( result . total . max , measurementsInputLatency [ i ] ) ;
217
- }
218
- result . keydown . average /= result . sampleCount ;
219
- result . input . average /= result . sampleCount ;
220
- result . render . average /= result . sampleCount ;
221
- result . total . average /= result . sampleCount ;
222
211
212
+ // Clear the cumulative measurements
213
+ clearCumulativeMeasurement ( totalKeydownTime ) ;
214
+ clearCumulativeMeasurement ( totalInputTime ) ;
215
+ clearCumulativeMeasurement ( totalRenderTime ) ;
216
+ clearCumulativeMeasurement ( totalInputLatencyTime ) ;
223
217
measurementsCount = 0 ;
218
+
224
219
return result ;
225
220
}
226
221
227
- function createSingleMeasurement ( ) : IInputLatencySingleMeasurement {
228
- return { average : 0 , min : Number . MAX_VALUE , max : 0 } ;
222
+ function cumulativeToFinalMeasurement ( cumulative : ICumulativeMeasurement ) : IInputLatencySingleMeasurement {
223
+ return {
224
+ average : cumulative . total / measurementsCount ,
225
+ max : cumulative . max ,
226
+ min : cumulative . min ,
227
+ } ;
228
+ }
229
+
230
+ function clearCumulativeMeasurement ( cumulative : ICumulativeMeasurement ) : void {
231
+ cumulative . total = 0 ;
232
+ cumulative . min = Number . MAX_VALUE ;
233
+ cumulative . max = 0 ;
229
234
}
230
235
231
236
}
0 commit comments