From b112fdf8ca17a71374e29053d1b2a0523e98fb70 Mon Sep 17 00:00:00 2001 From: Michael Mainguy Date: Mon, 11 Aug 2025 12:36:28 -0500 Subject: [PATCH] Update duration calculation to represent client-side time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Change Duration from network transfer time to client-side time - Duration = Total Response Time - Server Latency - This includes queuing, DNS, connection, SSL, and download time - Excludes server processing time, giving clearer client-side optimization insights - Add downloadTime field for pure response body transfer time - Update tooltip definition to reflect new calculation meaning Mathematical verification: - Total Response Time = Queue + DNS + Connection + SSL + Server + Download - Server Latency = Server processing time only - Duration = Total - Server = Queue + DNS + Connection + SSL + Download This provides more meaningful client-side performance metrics for optimization. Duration now represents time the browser spends vs. time the server spends. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../lib/httpRequestProcessor.ts | 45 ++++++------------- .../httprequestviewer/types/httpRequest.ts | 1 + src/components/shared/tooltipDefinitions.ts | 6 +-- 3 files changed, 17 insertions(+), 35 deletions(-) diff --git a/src/components/httprequestviewer/lib/httpRequestProcessor.ts b/src/components/httprequestviewer/lib/httpRequestProcessor.ts index 69ea4ab..a99c115 100644 --- a/src/components/httprequestviewer/lib/httpRequestProcessor.ts +++ b/src/components/httprequestviewer/lib/httpRequestProcessor.ts @@ -121,40 +121,15 @@ export const calculateDurations = (request: HTTPRequest): void => { lastDataTimestamp = request.events.finishLoading.ts } - // Chrome DevTools Duration Calculation: - // Duration = Total time from request start to completion (excludes queuing) - // This matches Chrome DevTools "Duration" column in Network tab - - if (timingData?.requestTime && timingData?.sendStart !== undefined && timingData?.receiveHeadersEnd !== undefined) { - // Chrome DevTools standard method: sendStart to receiveHeadersEnd - // This excludes queuing/DNS/connection time and measures actual network time - const networkDurationMs = timingData.receiveHeadersEnd - timingData.sendStart - request.timing.duration = networkDurationMs * 1000 // Convert to microseconds - - // If we have response body data, extend duration to last data chunk - if (lastDataTimestamp) { - const sendStartTimeUs = (timingData.requestTime * 1000000) + (timingData.sendStart * 1000) - const bodyDuration = lastDataTimestamp - sendStartTimeUs - - // Use the longer of header completion or body completion - request.timing.duration = Math.max(request.timing.duration, bodyDuration) - } - - } else if (timingData?.requestTime && timingData?.receiveHeadersEnd !== undefined) { - // Fallback: use receiveHeadersEnd from requestTime (includes all phases) - request.timing.duration = timingData.receiveHeadersEnd * 1000 // Convert to microseconds - - } else if (lastDataTimestamp && timingData?.requestTime && timingData?.sendStart !== undefined) { - // Fallback: sendStart to last data (body download completion) - const sendStartTimeUs = (timingData.requestTime * 1000000) + (timingData.sendStart * 1000) - request.timing.duration = lastDataTimestamp - sendStartTimeUs - - } else if (lastDataTimestamp && timingData?.requestTime) { - // Final fallback: requestTime to last data (includes everything) - const requestTimeUs = timingData.requestTime * 1000000 - request.timing.duration = lastDataTimestamp - requestTimeUs + // Calculate Download Time (response body transfer time) + // This is the time from first response byte to last data chunk + if (timingData?.receiveHeadersStart !== undefined && lastDataTimestamp) { + const receiveHeadersStartUs = (timingData.requestTime * 1000000) + (timingData.receiveHeadersStart * 1000) + request.timing.downloadTime = Math.max(0, lastDataTimestamp - receiveHeadersStartUs) } + // Note: Duration will be calculated after Total Response Time and Server Latency are available + // Calculate Total Response Time (wall clock time from request initiation to completion) // Use the earliest request start time (timing.start) which includes queuing, not sendRequest.ts if (request.timing.start && lastDataTimestamp) { @@ -184,6 +159,12 @@ export const calculateDurations = (request: HTTPRequest): void => { request.timing.totalResponseTime = totalTime } + // Calculate Duration as Client-Side Time (Total Response Time - Server Latency) + // This represents time spent on the client side: queuing, network setup, and download + if (request.timing.totalResponseTime && request.timing.serverLatency) { + request.timing.duration = Math.max(0, request.timing.totalResponseTime - request.timing.serverLatency) + } + // Fallback to trace event timestamps if timing data unavailable if (!request.timing.duration && request.timing.end) { request.timing.duration = request.timing.end - request.timing.start diff --git a/src/components/httprequestviewer/types/httpRequest.ts b/src/components/httprequestviewer/types/httpRequest.ts index f47865a..36d2e04 100644 --- a/src/components/httprequestviewer/types/httpRequest.ts +++ b/src/components/httprequestviewer/types/httpRequest.ts @@ -46,6 +46,7 @@ export interface HTTPRequest { end?: number duration?: number totalResponseTime?: number + downloadTime?: number queueTime?: number serverLatency?: number networkDuration?: number diff --git a/src/components/shared/tooltipDefinitions.ts b/src/components/shared/tooltipDefinitions.ts index 89677fa..1d00109 100644 --- a/src/components/shared/tooltipDefinitions.ts +++ b/src/components/shared/tooltipDefinitions.ts @@ -156,9 +156,9 @@ export const TOOLTIP_DEFINITIONS: Record = [TooltipType.REQUEST_DURATION]: { title: "Request Duration", - description: "Total time from request start to completion, including all network phases and data transfer.", - lighthouseRelation: "Long durations for critical resources directly impact LCP, FCP, and Speed Index. Background resource duration affects overall performance score.", - calculation: "responseEnd - requestStart from Navigation Timing API.", + description: "Client-side time including queuing, network setup, and download. This is Total Response Time minus Server Latency.", + lighthouseRelation: "Long durations for critical resources directly impact LCP, FCP, and Speed Index. This represents time the browser spends waiting and downloading.", + calculation: "Total Response Time - Server Latency. Includes queuing, DNS, connection, SSL, and download time.", links: [ { text: "Optimize Resource Loading", url: "https://web.dev/articles/critical-rendering-path" } ]