in src/sdk/lh-trace-processor.ts [289:345]
static _riskPercentiles(
durations,
totalTime,
percentiles,
clippedLength = 0
) {
let busyTime = 0;
for (let i = 0; i < durations.length; i++) {
busyTime += durations[i];
}
busyTime -= clippedLength;
// Start with idle time already complete.
let completedTime = totalTime - busyTime;
let duration = 0;
let cdfTime = completedTime;
const results = [];
let durationIndex = -1;
let remainingCount = durations.length + 1;
if (clippedLength > 0) {
// If there was a clipped duration, one less in count since one hasn't started yet.
remainingCount--;
}
// Find percentiles of interest, in order.
for (const percentile of percentiles) {
// Loop over durations, calculating a CDF value for each until it is above
// the target percentile.
const percentileTime = percentile * totalTime;
while (cdfTime < percentileTime && durationIndex < durations.length - 1) {
completedTime += duration;
remainingCount -= duration < 0 ? -1 : 1;
if (clippedLength > 0 && clippedLength < durations[durationIndex + 1]) {
duration = -clippedLength;
clippedLength = 0;
} else {
durationIndex++;
duration = durations[durationIndex];
}
// Calculate value of CDF (multiplied by totalTime) for the end of this duration.
cdfTime = completedTime + Math.abs(duration) * remainingCount;
}
// Negative results are within idle time (0ms wait by definition), so clamp at zero.
results.push({
percentile,
time:
Math.max(0, (percentileTime - completedTime) / remainingCount) +
BASE_RESPONSE_LATENCY,
});
}
return results;
}