Skip to content

Commit 9f11171

Browse files
committed
Generate an object with input latency stats
1 parent b14969c commit 9f11171

File tree

1 file changed

+68
-15
lines changed

1 file changed

+68
-15
lines changed

src/vs/base/browser/performance.ts

Lines changed: 68 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export namespace inputLatency {
2626
const measurementsInput = new Float32Array(Constants.bufferLength);
2727
const measurementsRender = new Float32Array(Constants.bufferLength);
2828
const measurementsInputLatency = new Float32Array(Constants.bufferLength);
29-
let measurementsIndex = 0;
29+
let measurementsCount = 0;
3030

3131
export function markKeydownStart() {
3232
performance.mark('inputlatency/start');
@@ -64,7 +64,6 @@ export namespace inputLatency {
6464
}
6565

6666
function markRenderEnd() {
67-
// Only measure the first render after keyboard input
6867
performance.mark('render/end');
6968
state.render = EventPhase.Finished;
7069
record();
@@ -77,15 +76,15 @@ export namespace inputLatency {
7776

7877
function record() {
7978
// Skip recording this frame if the buffer is full
80-
if (measurementsIndex >= Constants.bufferLength) {
79+
if (measurementsCount >= Constants.bufferLength) {
8180
return;
8281
}
8382
// Selection and render must have finished to record
8483
if (state.selection !== EventPhase.Finished || state.render !== EventPhase.Finished) {
8584
return;
8685
}
87-
// Measures from cursor edit to the end of the task
88-
window.queueMicrotask(() => {
86+
// Finish the recording, using setImmediate to ensure that layout/paint is captured
87+
setImmediate(() => {
8988
if (state.keydown === EventPhase.Finished && state.input === EventPhase.Finished && state.selection === EventPhase.Finished && state.render === EventPhase.Finished) {
9089
performance.mark('inputlatency/end');
9190

@@ -94,26 +93,26 @@ export namespace inputLatency {
9493
performance.measure('render', 'render/start', 'render/end');
9594
performance.measure('inputlatency', 'inputlatency/start', 'inputlatency/end');
9695

97-
measurementsKeydown[measurementsIndex] = performance.getEntriesByName('keydown')[0].duration;
98-
measurementsInput[measurementsIndex] = performance.getEntriesByName('input')[0].duration;
99-
measurementsRender[measurementsIndex] = performance.getEntriesByName('render')[0].duration;
100-
measurementsInputLatency[measurementsIndex] = performance.getEntriesByName('inputlatency')[0].duration;
96+
measurementsKeydown[measurementsCount] = performance.getEntriesByName('keydown')[0].duration;
97+
measurementsInput[measurementsCount] = performance.getEntriesByName('input')[0].duration;
98+
measurementsRender[measurementsCount] = performance.getEntriesByName('render')[0].duration;
99+
measurementsInputLatency[measurementsCount] = performance.getEntriesByName('inputlatency')[0].duration;
101100

102101
console.info(
103-
`input latency=${measurementsInputLatency[measurementsIndex].toFixed(1)} [` +
104-
`keydown=${measurementsKeydown[measurementsIndex].toFixed(1)}, ` +
105-
`input=${measurementsInput[measurementsIndex].toFixed(1)}, ` +
106-
`render=${measurementsRender[measurementsIndex].toFixed(1)}` +
102+
`input latency=${measurementsInputLatency[measurementsCount].toFixed(1)} [` +
103+
`keydown=${measurementsKeydown[measurementsCount].toFixed(1)}, ` +
104+
`input=${measurementsInput[measurementsCount].toFixed(1)}, ` +
105+
`render=${measurementsRender[measurementsCount].toFixed(1)}` +
107106
`]`
108107
);
109108

110-
measurementsIndex++;
109+
measurementsCount++;
111110

112111
reset();
113112
}
114113
});
115114
}
116-
115+
setInterval(() => console.log(getAndClearMeasurements()), 10000);
117116
function reset() {
118117
performance.clearMarks('keydown/start');
119118
performance.clearMarks('keydown/end');
@@ -135,4 +134,58 @@ export namespace inputLatency {
135134
state.selection = EventPhase.Before;
136135
}
137136

137+
export interface IInputLatencyMeasurements {
138+
keydown: IInputLatencySingleMeasurement;
139+
input: IInputLatencySingleMeasurement;
140+
render: IInputLatencySingleMeasurement;
141+
total: IInputLatencySingleMeasurement;
142+
sampleCount: number;
143+
}
144+
145+
export interface IInputLatencySingleMeasurement {
146+
average: number;
147+
min: number;
148+
max: number;
149+
}
150+
151+
export function getAndClearMeasurements(): IInputLatencyMeasurements | undefined {
152+
if (measurementsCount === 0) {
153+
return undefined;
154+
}
155+
156+
// Calculate the average, min and max of each measurement
157+
const result = {
158+
keydown: createSingleMeasurement(),
159+
input: createSingleMeasurement(),
160+
render: createSingleMeasurement(),
161+
total: createSingleMeasurement(),
162+
sampleCount: measurementsCount
163+
};
164+
for (let i = 0; i < result.sampleCount; i++) {
165+
result.keydown.average += measurementsKeydown[i];
166+
result.input.average += measurementsInput[i];
167+
result.render.average += measurementsRender[i];
168+
result.total.average += measurementsInputLatency[i];
169+
result.keydown.min = Math.min(result.keydown.min, measurementsKeydown[i]);
170+
result.input.min = Math.min(result.input.min, measurementsInput[i]);
171+
result.render.min = Math.min(result.render.min, measurementsRender[i]);
172+
result.total.min = Math.min(result.total.min, measurementsInputLatency[i]);
173+
result.keydown.max = Math.max(result.keydown.max, measurementsKeydown[i]);
174+
result.input.max = Math.max(result.input.max, measurementsInput[i]);
175+
result.render.max = Math.max(result.render.max, measurementsRender[i]);
176+
result.total.max = Math.max(result.total.max, measurementsInputLatency[i]);
177+
}
178+
result.keydown.average /= result.sampleCount;
179+
result.input.average /= result.sampleCount;
180+
result.render.average /= result.sampleCount;
181+
result.total.average /= result.sampleCount;
182+
183+
measurementsCount = 0;
184+
return result;
185+
}
186+
187+
function createSingleMeasurement(): IInputLatencySingleMeasurement {
188+
return { average: 0, min: Number.MAX_VALUE, max: 0 };
189+
}
190+
138191
}

0 commit comments

Comments
 (0)