Update duration calculation to represent client-side time
- 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 <noreply@anthropic.com>
This commit is contained in:
parent
4236ed0c55
commit
b112fdf8ca
@ -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
|
||||
|
@ -46,6 +46,7 @@ export interface HTTPRequest {
|
||||
end?: number
|
||||
duration?: number
|
||||
totalResponseTime?: number
|
||||
downloadTime?: number
|
||||
queueTime?: number
|
||||
serverLatency?: number
|
||||
networkDuration?: number
|
||||
|
@ -156,9 +156,9 @@ export const TOOLTIP_DEFINITIONS: Record<TooltipTypeValues, TooltipDefinition> =
|
||||
|
||||
[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" }
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user