UNPKG

@zendesk/react-measure-timing-hooks

Version:

react hooks for measuring time to interactive and time to render of components

108 lines 5.82 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createCPUIdleProcessor = createCPUIdleProcessor; const DEFAULT_QUIET_WINDOW_DURATION = 2_000; // Google used 2 seconds const DEFAULT_CLUSTER_PADDING = 1_000; // Google used 1 second const DEFAULT_HEAVY_CLUSTER_THRESHOLD = 250; // Google used 250ms const isLongTask = (entry) => entry.entryType === 'longtask' || entry.entryType === 'long-animation-frame'; function createCPUIdleProcessor(fmpOrEntry, { clusterPadding = DEFAULT_CLUSTER_PADDING, heavyClusterThreshold = DEFAULT_HEAVY_CLUSTER_THRESHOLD, getQuietWindowDuration, } = {}) { const fmp = typeof fmpOrEntry === 'number' ? fmpOrEntry : fmpOrEntry.startTime + fmpOrEntry.duration; let possibleFirstCPUIdleTimestamp = fmp; let possibleFirstCPUIdleEntry = typeof fmpOrEntry === 'number' ? null : fmpOrEntry; let longTaskClusterDurationTotal = 0; // Total duration of the current long task cluster // TODO: potentially assume that FMP point is as if inside of a heavy cluster already, this could be done by setting this value to fmp let endTimeStampOfLastLongTask = null; // End timestamp of the last long task let lastLongTask = null; const returnType = typeof fmpOrEntry === 'number' ? 'number' : 'object'; function checkIfQuietWindowPassed(time, quietWindowDuration = getQuietWindowDuration?.(time, fmp) ?? DEFAULT_QUIET_WINDOW_DURATION) { if (time - possibleFirstCPUIdleTimestamp > quietWindowDuration) { // Return the first CPU idle timestamp if in a quiet window return { firstCpuIdle: (returnType === 'object' ? possibleFirstCPUIdleEntry : possibleFirstCPUIdleTimestamp), }; } return { nextCheck: time + quietWindowDuration }; } function processPerformanceEntry(entry) { const entryEndTime = entry.startTime + entry.duration; const isEntryLongTask = isLongTask(entry); const quietWindowDuration = getQuietWindowDuration?.(entryEndTime, fmp) ?? DEFAULT_QUIET_WINDOW_DURATION; const quietWindowCheck = checkIfQuietWindowPassed( // is not processing a long task, we can assume current clock time is the end time isEntryLongTask ? entry.startTime : entryEndTime, quietWindowDuration); if (endTimeStampOfLastLongTask === null) { // Check if a quiet window has passed without seeing any long tasks if ('firstCpuIdle' in quietWindowCheck) { return quietWindowCheck; } // If this is the first long task if (isEntryLongTask) { // Update the end timestamp of the last long task and initialize the cluster endTimeStampOfLastLongTask = entryEndTime; lastLongTask = entry; // if this longtask overlaps FMP, then push the first CPU idle timestamp to the end of it if (entry.startTime - fmp < 0) { longTaskClusterDurationTotal = entry.duration - Math.abs(entry.startTime - fmp); if (endTimeStampOfLastLongTask > fmp) { // Move to the end of the cluster: possibleFirstCPUIdleTimestamp = endTimeStampOfLastLongTask; possibleFirstCPUIdleEntry = entry; } } else { longTaskClusterDurationTotal = entry.duration; } } return quietWindowCheck; } // Calculate time since the last long task const gapSincePreviousTask = entry.startTime - endTimeStampOfLastLongTask; if (isEntryLongTask && gapSincePreviousTask < clusterPadding && gapSincePreviousTask > 0) { // Continue to expand the existing cluster // If less than 1 second since the last long task // Include the time passed since the last long task in the cluster duration longTaskClusterDurationTotal += gapSincePreviousTask + entry.duration; endTimeStampOfLastLongTask = entryEndTime; // Update the end timestamp of the last long task lastLongTask = entry; // If the cluster duration exceeds 250ms, update the first CPU idle timestamp if (longTaskClusterDurationTotal >= heavyClusterThreshold && endTimeStampOfLastLongTask > fmp) { // Met criteria for Heavy Cluster // Move to the end of the cluster possibleFirstCPUIdleTimestamp = endTimeStampOfLastLongTask; possibleFirstCPUIdleEntry = lastLongTask; } } else { // either the quiet window has passed, or we're going to start a new long task cluster // If no new long tasks have occurred in the last quietWindowDuration // then we found our First CPU Idle if ('firstCpuIdle' in quietWindowCheck) { return quietWindowCheck; } if (isEntryLongTask) { // Start a new cluster longTaskClusterDurationTotal = entry.duration; // Reset the cluster duration with the current task endTimeStampOfLastLongTask = entryEndTime; // Update the end timestamp of the last long task lastLongTask = entry; // possibleFirstCPUIdleTimestamp remains unchanged, // because we don't know if it's a light or heavy cluster yet } } return quietWindowCheck; } return { processPerformanceEntry, checkIfQuietWindowPassed, }; } //# sourceMappingURL=firstCPUIdle.js.map