@paulirish/trace_engine 0.0.43 → 0.0.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.tmp/tsbuildinfo/tsconfig.tsbuildinfo +1 -1
- package/locales/en-US.json +5 -2
- package/locales/en-XL.json +5 -2
- package/models/trace/ModelImpl.d.ts +0 -1
- package/models/trace/ModelImpl.js +0 -3
- package/models/trace/ModelImpl.js.map +1 -1
- package/models/trace/extras/ThirdParties.d.ts +2 -1
- package/models/trace/extras/ThirdParties.js +26 -7
- package/models/trace/extras/ThirdParties.js.map +1 -1
- package/models/trace/handlers/InitiatorsHandler.js +0 -46
- package/models/trace/handlers/InitiatorsHandler.js.map +1 -1
- package/models/trace/helpers/Timing.d.ts +0 -1
- package/models/trace/helpers/Timing.js +0 -7
- package/models/trace/helpers/Timing.js.map +1 -1
- package/models/trace/helpers/Trace.d.ts +0 -1
- package/models/trace/helpers/Trace.js +0 -3
- package/models/trace/helpers/Trace.js.map +1 -1
- package/models/trace/insights/CLSCulprits.js +1 -1
- package/models/trace/insights/DOMSize.js +1 -1
- package/models/trace/insights/DocumentLatency.js +1 -1
- package/models/trace/insights/FontDisplay.js +1 -1
- package/models/trace/insights/ForcedReflow.js +1 -1
- package/models/trace/insights/ImageDelivery.d.ts +1 -0
- package/models/trace/insights/ImageDelivery.js +9 -2
- package/models/trace/insights/ImageDelivery.js.map +1 -1
- package/models/trace/insights/InteractionToNextPaint.js +1 -1
- package/models/trace/insights/LCPDiscovery.d.ts +4 -0
- package/models/trace/insights/LCPDiscovery.js +11 -2
- package/models/trace/insights/LCPDiscovery.js.map +1 -1
- package/models/trace/insights/LCPPhases.js +1 -1
- package/models/trace/insights/LongCriticalNetworkTree.js +1 -1
- package/models/trace/insights/RenderBlocking.js +1 -1
- package/models/trace/insights/SlowCSSSelector.js +1 -1
- package/models/trace/insights/ThirdParties.d.ts +4 -2
- package/models/trace/insights/ThirdParties.js +5 -3
- package/models/trace/insights/ThirdParties.js.map +1 -1
- package/models/trace/insights/Viewport.js +1 -1
- package/models/trace/insights/types.d.ts +3 -3
- package/models/trace/lantern/graph/BaseNode.js +1 -0
- package/models/trace/lantern/graph/BaseNode.js.map +1 -1
- package/models/trace/lantern/graph/PageDependencyGraph.js +1 -0
- package/models/trace/lantern/graph/PageDependencyGraph.js.map +1 -1
- package/models/trace/lantern/simulation/Simulator.js +1 -0
- package/models/trace/lantern/simulation/Simulator.js.map +1 -1
- package/models/trace/lantern/simulation/TCPConnection.d.ts +0 -1
- package/models/trace/lantern/simulation/TCPConnection.js +0 -3
- package/models/trace/lantern/simulation/TCPConnection.js.map +1 -1
- package/models/trace/types/Extensions.d.ts +0 -1
- package/models/trace/types/Extensions.js +0 -3
- package/models/trace/types/Extensions.js.map +1 -1
- package/models/trace/types/TraceEvents.d.ts +0 -9
- package/models/trace/types/TraceEvents.js +0 -3
- package/models/trace/types/TraceEvents.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageDependencyGraph.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/graph/PageDependencyGraph.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Core from '../core/core.js';\nimport type * as Lantern from '../types/types.js';\n\nimport type {Node} from './BaseNode.js';\nimport {CPUNode} from './CPUNode.js';\nimport {NetworkNode} from './NetworkNode.js';\n\n// COMPAT: m71+ We added RunTask to `disabled-by-default-lighthouse`\nconst SCHEDULABLE_TASK_TITLE_LH = 'RunTask';\n// m69-70 DoWork is different and we now need RunTask, see https://bugs.chromium.org/p/chromium/issues/detail?id=871204#c11\nconst SCHEDULABLE_TASK_TITLE_ALT1 = 'ThreadControllerImpl::RunTask';\n// In m66-68 refactored to this task title, https://crrev.com/c/883346\nconst SCHEDULABLE_TASK_TITLE_ALT2 = 'ThreadControllerImpl::DoWork';\n// m65 and earlier\nconst SCHEDULABLE_TASK_TITLE_ALT3 = 'TaskQueueManager::ProcessTaskFromWorkQueue';\n\ninterface NetworkNodeOutput {\n nodes: Array<NetworkNode>;\n idToNodeMap: Map<string, NetworkNode>;\n urlToNodeMap: Map<string, Array<NetworkNode>>;\n frameIdToNodeMap: Map<string, NetworkNode|null>;\n}\n\n// Shorter tasks have negligible impact on simulation results.\nconst SIGNIFICANT_DUR_THRESHOLD_MS = 10;\n\n// TODO: video files tend to be enormous and throw off all graph traversals, move this ignore\n// into estimation logic when we use the dependency graph for other purposes.\nconst IGNORED_MIME_TYPES_REGEX = /^video/;\n\nclass PageDependencyGraph {\n static getNetworkInitiators(request: Lantern.NetworkRequest): string[] {\n if (!request.initiator) {\n return [];\n }\n if (request.initiator.url) {\n return [request.initiator.url];\n }\n if (request.initiator.type === 'script') {\n // Script initiators have the stack of callFrames from all functions that led to this request.\n // If async stacks are enabled, then the stack will also have the parent functions that asynchronously\n // led to this request chained in the `parent` property.\n const scriptURLs = new Set<string>();\n let stack = request.initiator.stack;\n while (stack) {\n const callFrames = stack.callFrames || [];\n for (const frame of callFrames) {\n if (frame.url) {\n scriptURLs.add(frame.url);\n }\n }\n\n stack = stack.parent;\n }\n\n return Array.from(scriptURLs);\n }\n\n return [];\n }\n\n static getNetworkNodeOutput(networkRequests: Lantern.NetworkRequest[]): NetworkNodeOutput {\n const nodes: Array<NetworkNode> = [];\n const idToNodeMap = new Map<string, NetworkNode>();\n const urlToNodeMap = new Map<string, Array<NetworkNode>>();\n const frameIdToNodeMap = new Map<string, NetworkNode|null>();\n\n networkRequests.forEach(request => {\n if (IGNORED_MIME_TYPES_REGEX.test(request.mimeType)) {\n return;\n }\n if (request.fromWorker) {\n return;\n }\n\n // Network requestIds can be duplicated for an unknown reason\n // Suffix all subsequent requests with `:duplicate` until it's unique\n // NOTE: This should never happen with modern NetworkRequest library, but old fixtures\n // might still have this issue.\n while (idToNodeMap.has(request.requestId)) {\n request.requestId += ':duplicate';\n }\n\n const node = new NetworkNode(request);\n nodes.push(node);\n\n const urlList = urlToNodeMap.get(request.url) || [];\n urlList.push(node);\n\n idToNodeMap.set(request.requestId, node);\n urlToNodeMap.set(request.url, urlList);\n\n // If the request was for the root document of an iframe, save an entry in our\n // map so we can link up the task `args.data.frame` dependencies later in graph creation.\n if (request.frameId && request.resourceType === 'Document' && request.documentURL === request.url) {\n // If there's ever any ambiguity, permanently set the value to `false` to avoid loops in the graph.\n const value = frameIdToNodeMap.has(request.frameId) ? null : node;\n frameIdToNodeMap.set(request.frameId, value);\n }\n });\n\n return {nodes, idToNodeMap, urlToNodeMap, frameIdToNodeMap};\n }\n\n static isScheduleableTask(evt: Lantern.TraceEvent): boolean {\n return evt.name === SCHEDULABLE_TASK_TITLE_LH || evt.name === SCHEDULABLE_TASK_TITLE_ALT1 ||\n evt.name === SCHEDULABLE_TASK_TITLE_ALT2 || evt.name === SCHEDULABLE_TASK_TITLE_ALT3;\n }\n\n /**\n * There should *always* be at least one top level event, having 0 typically means something is\n * drastically wrong with the trace and we should just give up early and loudly.\n */\n static assertHasToplevelEvents(events: Lantern.TraceEvent[]): void {\n const hasToplevelTask = events.some(this.isScheduleableTask);\n if (!hasToplevelTask) {\n throw new Core.LanternError('Could not find any top level events');\n }\n }\n\n static getCPUNodes(mainThreadEvents: Lantern.TraceEvent[]): CPUNode[] {\n const nodes: CPUNode[] = [];\n let i = 0;\n\n PageDependencyGraph.assertHasToplevelEvents(mainThreadEvents);\n\n while (i < mainThreadEvents.length) {\n const evt = mainThreadEvents[i];\n i++;\n\n // Skip all trace events that aren't schedulable tasks with sizable duration\n if (!PageDependencyGraph.isScheduleableTask(evt) || !evt.dur) {\n continue;\n }\n\n let correctedEndTs: number|undefined = undefined;\n\n // Capture all events that occurred within the task\n const children: Lantern.TraceEvent[] = [];\n for (const endTime = evt.ts + evt.dur; i < mainThreadEvents.length && mainThreadEvents[i].ts < endTime; i++) {\n const event = mainThreadEvents[i];\n\n // Temporary fix for a Chrome bug where some RunTask events can be overlapping.\n // We correct that here be ensuring each RunTask ends at least 1 microsecond before the next\n // https://github.com/GoogleChrome/lighthouse/issues/15896\n // https://issues.chromium.org/issues/329678173\n if (PageDependencyGraph.isScheduleableTask(event) && event.dur) {\n correctedEndTs = event.ts - 1;\n break;\n }\n\n children.push(event);\n }\n\n nodes.push(new CPUNode(evt, children, correctedEndTs));\n }\n\n return nodes;\n }\n\n static linkNetworkNodes(rootNode: NetworkNode, networkNodeOutput: NetworkNodeOutput): void {\n networkNodeOutput.nodes.forEach(node => {\n const directInitiatorRequest = node.request.initiatorRequest || rootNode.request;\n const directInitiatorNode = networkNodeOutput.idToNodeMap.get(directInitiatorRequest.requestId) || rootNode;\n const canDependOnInitiator = !directInitiatorNode.isDependentOn(node) && node.canDependOn(directInitiatorNode);\n const initiators = PageDependencyGraph.getNetworkInitiators(node.request);\n if (initiators.length) {\n initiators.forEach(initiator => {\n const parentCandidates = networkNodeOutput.urlToNodeMap.get(initiator) || [];\n // Only add the edge if the parent is unambiguous with valid timing and isn't circular.\n if (parentCandidates.length === 1 && parentCandidates[0].startTime <= node.startTime &&\n !parentCandidates[0].isDependentOn(node)) {\n node.addDependency(parentCandidates[0]);\n } else if (canDependOnInitiator) {\n directInitiatorNode.addDependent(node);\n }\n });\n } else if (canDependOnInitiator) {\n directInitiatorNode.addDependent(node);\n }\n\n // Make sure the nodes are attached to the graph if the initiator information was invalid.\n if (node !== rootNode && node.getDependencies().length === 0 && node.canDependOn(rootNode)) {\n node.addDependency(rootNode);\n }\n\n if (!node.request.redirects) {\n return;\n }\n\n const redirects = [...node.request.redirects, node.request];\n for (let i = 1; i < redirects.length; i++) {\n const redirectNode = networkNodeOutput.idToNodeMap.get(redirects[i - 1].requestId);\n const actualNode = networkNodeOutput.idToNodeMap.get(redirects[i].requestId);\n if (actualNode && redirectNode) {\n actualNode.addDependency(redirectNode);\n }\n }\n });\n }\n\n static linkCPUNodes(rootNode: Node, networkNodeOutput: NetworkNodeOutput, cpuNodes: CPUNode[]): void {\n const linkableResourceTypes = new Set<Lantern.ResourceType|undefined>([\n 'XHR',\n 'Fetch',\n 'Script',\n ]);\n\n function addDependentNetworkRequest(cpuNode: CPUNode, reqId: string): void {\n const networkNode = networkNodeOutput.idToNodeMap.get(reqId);\n if (!networkNode ||\n // Ignore all network nodes that started before this CPU task started\n // A network request that started earlier could not possibly have been started by this task\n networkNode.startTime <= cpuNode.startTime) {\n return;\n }\n const {request} = networkNode;\n const resourceType = request.resourceType || request.redirectDestination?.resourceType;\n if (!linkableResourceTypes.has(resourceType)) {\n // We only link some resources to CPU nodes because we observe LCP simulation\n // regressions when including images, etc.\n return;\n }\n cpuNode.addDependent(networkNode);\n }\n\n /**\n * If the node has an associated frameId, then create a dependency on the root document request\n * for the frame. The task obviously couldn't have started before the frame was even downloaded.\n */\n function addDependencyOnFrame(cpuNode: CPUNode, frameId: string|undefined): void {\n if (!frameId) {\n return;\n }\n const networkNode = networkNodeOutput.frameIdToNodeMap.get(frameId);\n if (!networkNode) {\n return;\n }\n // Ignore all network nodes that started after this CPU task started\n // A network request that started after could not possibly be required this task\n if (networkNode.startTime >= cpuNode.startTime) {\n return;\n }\n cpuNode.addDependency(networkNode);\n }\n\n function addDependencyOnUrl(cpuNode: CPUNode, url: string): void {\n if (!url) {\n return;\n }\n // Allow network requests that end up to 100ms before the task started\n // Some script evaluations can start before the script finishes downloading\n const minimumAllowableTimeSinceNetworkNodeEnd = -100 * 1000;\n const candidates = networkNodeOutput.urlToNodeMap.get(url) || [];\n\n let minCandidate = null;\n let minDistance = Infinity;\n // Find the closest request that finished before this CPU task started\n for (const candidate of candidates) {\n // Explicitly ignore all requests that started after this CPU node\n // A network request that started after this task started cannot possibly be a dependency\n if (cpuNode.startTime <= candidate.startTime) {\n return;\n }\n\n const distance = cpuNode.startTime - candidate.endTime;\n if (distance >= minimumAllowableTimeSinceNetworkNodeEnd && distance < minDistance) {\n minCandidate = candidate;\n minDistance = distance;\n }\n }\n\n if (!minCandidate) {\n return;\n }\n cpuNode.addDependency(minCandidate);\n }\n\n const timers = new Map<string, CPUNode>();\n for (const node of cpuNodes) {\n for (const evt of node.childEvents) {\n if (!evt.args.data) {\n continue;\n }\n\n const argsUrl = evt.args.data.url;\n const stackTraceUrls = (evt.args.data.stackTrace || []).map(l => l.url).filter(Boolean);\n\n switch (evt.name) {\n case 'TimerInstall':\n // @ts-expect-error - 'TimerInstall' event means timerId exists.\n timers.set(evt.args.data.timerId, node);\n stackTraceUrls.forEach(url => addDependencyOnUrl(node, url));\n break;\n case 'TimerFire': {\n // @ts-expect-error - 'TimerFire' event means timerId exists.\n const installer = timers.get(evt.args.data.timerId);\n if (!installer || installer.endTime > node.startTime) {\n break;\n }\n installer.addDependent(node);\n break;\n }\n\n case 'InvalidateLayout':\n case 'ScheduleStyleRecalculation':\n addDependencyOnFrame(node, evt.args.data.frame);\n stackTraceUrls.forEach(url => addDependencyOnUrl(node, url));\n break;\n\n case 'EvaluateScript':\n addDependencyOnFrame(node, evt.args.data.frame);\n // @ts-expect-error - 'EvaluateScript' event means argsUrl is defined.\n addDependencyOnUrl(node, argsUrl);\n stackTraceUrls.forEach(url => addDependencyOnUrl(node, url));\n break;\n\n case 'XHRReadyStateChange':\n // Only create the dependency if the request was completed\n // 'XHRReadyStateChange' event means readyState is defined.\n if (evt.args.data.readyState !== 4) {\n break;\n }\n\n // @ts-expect-error - 'XHRReadyStateChange' event means argsUrl is defined.\n addDependencyOnUrl(node, argsUrl);\n stackTraceUrls.forEach(url => addDependencyOnUrl(node, url));\n break;\n\n case 'FunctionCall':\n case 'v8.compile':\n addDependencyOnFrame(node, evt.args.data.frame);\n // @ts-expect-error - events mean argsUrl is defined.\n addDependencyOnUrl(node, argsUrl);\n break;\n\n case 'ParseAuthorStyleSheet':\n addDependencyOnFrame(node, evt.args.data.frame);\n // @ts-expect-error - 'ParseAuthorStyleSheet' event means styleSheetUrl is defined.\n addDependencyOnUrl(node, evt.args.data.styleSheetUrl);\n break;\n\n case 'ResourceSendRequest':\n addDependencyOnFrame(node, evt.args.data.frame);\n // @ts-expect-error - 'ResourceSendRequest' event means requestId is defined.\n addDependentNetworkRequest(node, evt.args.data.requestId);\n stackTraceUrls.forEach(url => addDependencyOnUrl(node, url));\n break;\n }\n }\n\n // Nodes starting before the root node cannot depend on it.\n if (node.getNumberOfDependencies() === 0 && node.canDependOn(rootNode)) {\n node.addDependency(rootNode);\n }\n }\n\n // Second pass to prune the graph of short tasks.\n const minimumEvtDur = SIGNIFICANT_DUR_THRESHOLD_MS * 1000;\n let foundFirstLayout = false;\n let foundFirstPaint = false;\n let foundFirstParse = false;\n\n for (const node of cpuNodes) {\n // Don't prune if event is the first ParseHTML/Layout/Paint.\n // See https://github.com/GoogleChrome/lighthouse/issues/9627#issuecomment-526699524 for more.\n let isFirst = false;\n if (!foundFirstLayout && node.childEvents.some(evt => evt.name === 'Layout')) {\n isFirst = foundFirstLayout = true;\n }\n if (!foundFirstPaint && node.childEvents.some(evt => evt.name === 'Paint')) {\n isFirst = foundFirstPaint = true;\n }\n if (!foundFirstParse && node.childEvents.some(evt => evt.name === 'ParseHTML')) {\n isFirst = foundFirstParse = true;\n }\n\n if (isFirst || node.duration >= minimumEvtDur) {\n // Don't prune this node. The task is long / important so it will impact simulation.\n continue;\n }\n\n // Prune the node if it isn't highly connected to minimize graph size. Rewiring the graph\n // here replaces O(M + N) edges with (M * N) edges, which is fine if either M or N is at\n // most 1.\n if (node.getNumberOfDependencies() === 1 || node.getNumberOfDependents() <= 1) {\n PageDependencyGraph.pruneNode(node);\n }\n }\n }\n\n /**\n * Removes the given node from the graph, but retains all paths between its dependencies and\n * dependents.\n */\n static pruneNode(node: Node): void {\n const dependencies = node.getDependencies();\n const dependents = node.getDependents();\n for (const dependency of dependencies) {\n node.removeDependency(dependency);\n for (const dependent of dependents) {\n dependency.addDependent(dependent);\n }\n }\n for (const dependent of dependents) {\n node.removeDependent(dependent);\n }\n }\n\n /**\n * TODO: remove when CDT backend in Lighthouse is gone. Until then, this is a useful debugging tool\n * to find delta between using CDP or the trace to create the network requests.\n *\n * When a test fails using the trace backend, I enabled this debug method and copied the network\n * requests when CDP was used, then when trace is used, and diff'd them. This method helped\n * remove non-logical differences from the comparison (order of properties, slight rounding\n * discrepancies, removing object cycles, etc).\n *\n * When using for a unit test, make sure to do `.only` so you are getting what you expect.\n */\n static debugNormalizeRequests(lanternRequests: Lantern.NetworkRequest[]): void {\n for (const request of lanternRequests) {\n request.rendererStartTime = Math.round(request.rendererStartTime * 1000) / 1000;\n request.networkRequestTime = Math.round(request.networkRequestTime * 1000) / 1000;\n request.responseHeadersEndTime = Math.round(request.responseHeadersEndTime * 1000) / 1000;\n request.networkEndTime = Math.round(request.networkEndTime * 1000) / 1000;\n }\n\n for (const r of lanternRequests) {\n delete r.rawRequest;\n if (r.initiatorRequest) {\n // @ts-expect-error\n r.initiatorRequest = {id: r.initiatorRequest.requestId};\n }\n if (r.redirectDestination) {\n // @ts-expect-error\n r.redirectDestination = {id: r.redirectDestination.requestId};\n }\n if (r.redirectSource) {\n // @ts-expect-error\n r.redirectSource = {id: r.redirectSource.requestId};\n }\n if (r.redirects) {\n // @ts-expect-error\n r.redirects = r.redirects.map(r2 => r2.requestId);\n }\n }\n const requests: Lantern.NetworkRequest[] = lanternRequests\n .map(r => ({\n requestId: r.requestId,\n connectionId: r.connectionId,\n connectionReused: r.connectionReused,\n url: r.url,\n protocol: r.protocol,\n parsedURL: r.parsedURL,\n documentURL: r.documentURL,\n rendererStartTime: r.rendererStartTime,\n networkRequestTime: r.networkRequestTime,\n responseHeadersEndTime: r.responseHeadersEndTime,\n networkEndTime: r.networkEndTime,\n transferSize: r.transferSize,\n resourceSize: r.resourceSize,\n fromDiskCache: r.fromDiskCache,\n fromMemoryCache: r.fromMemoryCache,\n finished: r.finished,\n statusCode: r.statusCode,\n redirectSource: r.redirectSource,\n redirectDestination: r.redirectDestination,\n redirects: r.redirects,\n failed: r.failed,\n initiator: r.initiator,\n timing: r.timing ? {\n requestTime: r.timing.requestTime,\n proxyStart: r.timing.proxyStart,\n proxyEnd: r.timing.proxyEnd,\n dnsStart: r.timing.dnsStart,\n dnsEnd: r.timing.dnsEnd,\n connectStart: r.timing.connectStart,\n connectEnd: r.timing.connectEnd,\n sslStart: r.timing.sslStart,\n sslEnd: r.timing.sslEnd,\n workerStart: r.timing.workerStart,\n workerReady: r.timing.workerReady,\n workerFetchStart: r.timing.workerFetchStart,\n workerRespondWithSettled: r.timing.workerRespondWithSettled,\n sendStart: r.timing.sendStart,\n sendEnd: r.timing.sendEnd,\n pushStart: r.timing.pushStart,\n pushEnd: r.timing.pushEnd,\n receiveHeadersStart: r.timing.receiveHeadersStart,\n receiveHeadersEnd: r.timing.receiveHeadersEnd,\n } :\n r.timing,\n resourceType: r.resourceType,\n mimeType: r.mimeType,\n priority: r.priority,\n initiatorRequest: r.initiatorRequest,\n frameId: r.frameId,\n fromWorker: r.fromWorker,\n isLinkPreload: r.isLinkPreload,\n serverResponseTime: r.serverResponseTime,\n }))\n .filter(r => !r.fromWorker);\n\n const debug = requests;\n // Set breakpoint here.\n // Copy `debug` and compare with https://www.diffchecker.com/text-compare/\n // eslint-disable-next-line no-console\n console.log(debug);\n }\n\n static createGraph(\n mainThreadEvents: Lantern.TraceEvent[], networkRequests: Lantern.NetworkRequest[],\n url: Lantern.Simulation.URL): Node {\n // This is for debugging trace/devtoolslog network records.\n // const debug = PageDependencyGraph.debugNormalizeRequests(networkRequests);\n const networkNodeOutput = PageDependencyGraph.getNetworkNodeOutput(networkRequests);\n const cpuNodes = PageDependencyGraph.getCPUNodes(mainThreadEvents);\n const {requestedUrl, mainDocumentUrl} = url;\n if (!requestedUrl) {\n throw new Core.LanternError('requestedUrl is required to get the root request');\n }\n if (!mainDocumentUrl) {\n throw new Core.LanternError('mainDocumentUrl is required to get the main resource');\n }\n\n const rootRequest = Core.NetworkAnalyzer.findResourceForUrl(networkRequests, requestedUrl);\n if (!rootRequest) {\n throw new Core.LanternError('rootRequest not found');\n }\n const rootNode = networkNodeOutput.idToNodeMap.get(rootRequest.requestId);\n if (!rootNode) {\n throw new Core.LanternError('rootNode not found');\n }\n const mainDocumentRequest = Core.NetworkAnalyzer.findLastDocumentForUrl(networkRequests, mainDocumentUrl);\n if (!mainDocumentRequest) {\n throw new Core.LanternError('mainDocumentRequest not found');\n }\n const mainDocumentNode = networkNodeOutput.idToNodeMap.get(mainDocumentRequest.requestId);\n if (!mainDocumentNode) {\n throw new Core.LanternError('mainDocumentNode not found');\n }\n\n PageDependencyGraph.linkNetworkNodes(rootNode, networkNodeOutput);\n PageDependencyGraph.linkCPUNodes(rootNode, networkNodeOutput, cpuNodes);\n mainDocumentNode.setIsMainDocument(true);\n\n if (NetworkNode.hasCycle(rootNode)) {\n throw new Core.LanternError('Invalid dependency graph created, cycle detected');\n }\n\n return rootNode;\n }\n\n static printGraph(rootNode: Node, widthInCharacters = 100): void {\n function padRight(str: string, target: number, padChar = ' '): string {\n return str + padChar.repeat(Math.max(target - str.length, 0));\n }\n\n const nodes: Node[] = [];\n rootNode.traverse(node => nodes.push(node));\n nodes.sort((a, b) => a.startTime - b.startTime);\n\n const min = nodes[0].startTime;\n const max = nodes.reduce((max, node) => Math.max(max, node.endTime), 0);\n\n const totalTime = max - min;\n const timePerCharacter = totalTime / widthInCharacters;\n nodes.forEach(node => {\n const offset = Math.round((node.startTime - min) / timePerCharacter);\n const length = Math.ceil((node.endTime - node.startTime) / timePerCharacter);\n const bar = padRight('', offset) + padRight('', length, '=');\n\n // @ts-expect-error -- disambiguate displayName from across possible Node types.\n const displayName = node.request ? node.request.url : node.type;\n // eslint-disable-next-line\n console.log(padRight(bar, widthInCharacters), `| ${displayName.slice(0, 30)}`);\n });\n }\n}\n\nexport {PageDependencyGraph};\n"]}
|
|
1
|
+
{"version":3,"file":"PageDependencyGraph.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/graph/PageDependencyGraph.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Core from '../core/core.js';\nimport type * as Lantern from '../types/types.js';\n\nimport type {Node} from './BaseNode.js';\nimport {CPUNode} from './CPUNode.js';\nimport {NetworkNode} from './NetworkNode.js';\n\n// COMPAT: m71+ We added RunTask to `disabled-by-default-lighthouse`\nconst SCHEDULABLE_TASK_TITLE_LH = 'RunTask';\n// m69-70 DoWork is different and we now need RunTask, see https://bugs.chromium.org/p/chromium/issues/detail?id=871204#c11\nconst SCHEDULABLE_TASK_TITLE_ALT1 = 'ThreadControllerImpl::RunTask';\n// In m66-68 refactored to this task title, https://crrev.com/c/883346\nconst SCHEDULABLE_TASK_TITLE_ALT2 = 'ThreadControllerImpl::DoWork';\n// m65 and earlier\nconst SCHEDULABLE_TASK_TITLE_ALT3 = 'TaskQueueManager::ProcessTaskFromWorkQueue';\n\ninterface NetworkNodeOutput {\n nodes: Array<NetworkNode>;\n idToNodeMap: Map<string, NetworkNode>;\n urlToNodeMap: Map<string, Array<NetworkNode>>;\n frameIdToNodeMap: Map<string, NetworkNode|null>;\n}\n\n// Shorter tasks have negligible impact on simulation results.\nconst SIGNIFICANT_DUR_THRESHOLD_MS = 10;\n\n// TODO: video files tend to be enormous and throw off all graph traversals, move this ignore\n// into estimation logic when we use the dependency graph for other purposes.\nconst IGNORED_MIME_TYPES_REGEX = /^video/;\n\nclass PageDependencyGraph {\n static getNetworkInitiators(request: Lantern.NetworkRequest): string[] {\n if (!request.initiator) {\n return [];\n }\n if (request.initiator.url) {\n return [request.initiator.url];\n }\n if (request.initiator.type === 'script') {\n // Script initiators have the stack of callFrames from all functions that led to this request.\n // If async stacks are enabled, then the stack will also have the parent functions that asynchronously\n // led to this request chained in the `parent` property.\n const scriptURLs = new Set<string>();\n let stack = request.initiator.stack;\n while (stack) {\n const callFrames = stack.callFrames || [];\n for (const frame of callFrames) {\n if (frame.url) {\n scriptURLs.add(frame.url);\n }\n }\n\n stack = stack.parent;\n }\n\n return Array.from(scriptURLs);\n }\n\n return [];\n }\n\n static getNetworkNodeOutput(networkRequests: Lantern.NetworkRequest[]): NetworkNodeOutput {\n const nodes: Array<NetworkNode> = [];\n const idToNodeMap = new Map<string, NetworkNode>();\n const urlToNodeMap = new Map<string, Array<NetworkNode>>();\n const frameIdToNodeMap = new Map<string, NetworkNode|null>();\n\n networkRequests.forEach(request => {\n if (IGNORED_MIME_TYPES_REGEX.test(request.mimeType)) {\n return;\n }\n if (request.fromWorker) {\n return;\n }\n\n // Network requestIds can be duplicated for an unknown reason\n // Suffix all subsequent requests with `:duplicate` until it's unique\n // NOTE: This should never happen with modern NetworkRequest library, but old fixtures\n // might still have this issue.\n while (idToNodeMap.has(request.requestId)) {\n request.requestId += ':duplicate';\n }\n\n const node = new NetworkNode(request);\n nodes.push(node);\n\n const urlList = urlToNodeMap.get(request.url) || [];\n urlList.push(node);\n\n idToNodeMap.set(request.requestId, node);\n urlToNodeMap.set(request.url, urlList);\n\n // If the request was for the root document of an iframe, save an entry in our\n // map so we can link up the task `args.data.frame` dependencies later in graph creation.\n if (request.frameId && request.resourceType === 'Document' && request.documentURL === request.url) {\n // If there's ever any ambiguity, permanently set the value to `false` to avoid loops in the graph.\n const value = frameIdToNodeMap.has(request.frameId) ? null : node;\n frameIdToNodeMap.set(request.frameId, value);\n }\n });\n\n return {nodes, idToNodeMap, urlToNodeMap, frameIdToNodeMap};\n }\n\n static isScheduleableTask(evt: Lantern.TraceEvent): boolean {\n return evt.name === SCHEDULABLE_TASK_TITLE_LH || evt.name === SCHEDULABLE_TASK_TITLE_ALT1 ||\n evt.name === SCHEDULABLE_TASK_TITLE_ALT2 || evt.name === SCHEDULABLE_TASK_TITLE_ALT3;\n }\n\n /**\n * There should *always* be at least one top level event, having 0 typically means something is\n * drastically wrong with the trace and we should just give up early and loudly.\n */\n static assertHasToplevelEvents(events: Lantern.TraceEvent[]): void {\n const hasToplevelTask = events.some(this.isScheduleableTask);\n if (!hasToplevelTask) {\n throw new Core.LanternError('Could not find any top level events');\n }\n }\n\n static getCPUNodes(mainThreadEvents: Lantern.TraceEvent[]): CPUNode[] {\n const nodes: CPUNode[] = [];\n let i = 0;\n\n PageDependencyGraph.assertHasToplevelEvents(mainThreadEvents);\n\n while (i < mainThreadEvents.length) {\n const evt = mainThreadEvents[i];\n i++;\n\n // Skip all trace events that aren't schedulable tasks with sizable duration\n if (!PageDependencyGraph.isScheduleableTask(evt) || !evt.dur) {\n continue;\n }\n\n let correctedEndTs: number|undefined = undefined;\n\n // Capture all events that occurred within the task\n const children: Lantern.TraceEvent[] = [];\n for (const endTime = evt.ts + evt.dur; i < mainThreadEvents.length && mainThreadEvents[i].ts < endTime; i++) {\n const event = mainThreadEvents[i];\n\n // Temporary fix for a Chrome bug where some RunTask events can be overlapping.\n // We correct that here be ensuring each RunTask ends at least 1 microsecond before the next\n // https://github.com/GoogleChrome/lighthouse/issues/15896\n // https://issues.chromium.org/issues/329678173\n if (PageDependencyGraph.isScheduleableTask(event) && event.dur) {\n correctedEndTs = event.ts - 1;\n break;\n }\n\n children.push(event);\n }\n\n nodes.push(new CPUNode(evt, children, correctedEndTs));\n }\n\n return nodes;\n }\n\n static linkNetworkNodes(rootNode: NetworkNode, networkNodeOutput: NetworkNodeOutput): void {\n networkNodeOutput.nodes.forEach(node => {\n const directInitiatorRequest = node.request.initiatorRequest || rootNode.request;\n const directInitiatorNode = networkNodeOutput.idToNodeMap.get(directInitiatorRequest.requestId) || rootNode;\n const canDependOnInitiator = !directInitiatorNode.isDependentOn(node) && node.canDependOn(directInitiatorNode);\n const initiators = PageDependencyGraph.getNetworkInitiators(node.request);\n if (initiators.length) {\n initiators.forEach(initiator => {\n const parentCandidates = networkNodeOutput.urlToNodeMap.get(initiator) || [];\n // Only add the edge if the parent is unambiguous with valid timing and isn't circular.\n if (parentCandidates.length === 1 && parentCandidates[0].startTime <= node.startTime &&\n !parentCandidates[0].isDependentOn(node)) {\n node.addDependency(parentCandidates[0]);\n } else if (canDependOnInitiator) {\n directInitiatorNode.addDependent(node);\n }\n });\n } else if (canDependOnInitiator) {\n directInitiatorNode.addDependent(node);\n }\n\n // Make sure the nodes are attached to the graph if the initiator information was invalid.\n if (node !== rootNode && node.getDependencies().length === 0 && node.canDependOn(rootNode)) {\n node.addDependency(rootNode);\n }\n\n if (!node.request.redirects) {\n return;\n }\n\n const redirects = [...node.request.redirects, node.request];\n for (let i = 1; i < redirects.length; i++) {\n const redirectNode = networkNodeOutput.idToNodeMap.get(redirects[i - 1].requestId);\n const actualNode = networkNodeOutput.idToNodeMap.get(redirects[i].requestId);\n if (actualNode && redirectNode) {\n actualNode.addDependency(redirectNode);\n }\n }\n });\n }\n\n static linkCPUNodes(rootNode: Node, networkNodeOutput: NetworkNodeOutput, cpuNodes: CPUNode[]): void {\n const linkableResourceTypes = new Set<Lantern.ResourceType|undefined>([\n 'XHR',\n 'Fetch',\n 'Script',\n ]);\n\n function addDependentNetworkRequest(cpuNode: CPUNode, reqId: string): void {\n const networkNode = networkNodeOutput.idToNodeMap.get(reqId);\n if (!networkNode ||\n // Ignore all network nodes that started before this CPU task started\n // A network request that started earlier could not possibly have been started by this task\n networkNode.startTime <= cpuNode.startTime) {\n return;\n }\n const {request} = networkNode;\n const resourceType = request.resourceType || request.redirectDestination?.resourceType;\n if (!linkableResourceTypes.has(resourceType)) {\n // We only link some resources to CPU nodes because we observe LCP simulation\n // regressions when including images, etc.\n return;\n }\n cpuNode.addDependent(networkNode);\n }\n\n /**\n * If the node has an associated frameId, then create a dependency on the root document request\n * for the frame. The task obviously couldn't have started before the frame was even downloaded.\n */\n function addDependencyOnFrame(cpuNode: CPUNode, frameId: string|undefined): void {\n if (!frameId) {\n return;\n }\n const networkNode = networkNodeOutput.frameIdToNodeMap.get(frameId);\n if (!networkNode) {\n return;\n }\n // Ignore all network nodes that started after this CPU task started\n // A network request that started after could not possibly be required this task\n if (networkNode.startTime >= cpuNode.startTime) {\n return;\n }\n cpuNode.addDependency(networkNode);\n }\n\n function addDependencyOnUrl(cpuNode: CPUNode, url: string): void {\n if (!url) {\n return;\n }\n // Allow network requests that end up to 100ms before the task started\n // Some script evaluations can start before the script finishes downloading\n const minimumAllowableTimeSinceNetworkNodeEnd = -100 * 1000;\n const candidates = networkNodeOutput.urlToNodeMap.get(url) || [];\n\n let minCandidate = null;\n let minDistance = Infinity;\n // Find the closest request that finished before this CPU task started\n for (const candidate of candidates) {\n // Explicitly ignore all requests that started after this CPU node\n // A network request that started after this task started cannot possibly be a dependency\n if (cpuNode.startTime <= candidate.startTime) {\n return;\n }\n\n const distance = cpuNode.startTime - candidate.endTime;\n if (distance >= minimumAllowableTimeSinceNetworkNodeEnd && distance < minDistance) {\n minCandidate = candidate;\n minDistance = distance;\n }\n }\n\n if (!minCandidate) {\n return;\n }\n cpuNode.addDependency(minCandidate);\n }\n\n const timers = new Map<string, CPUNode>();\n for (const node of cpuNodes) {\n for (const evt of node.childEvents) {\n if (!evt.args.data) {\n continue;\n }\n\n const argsUrl = evt.args.data.url;\n const stackTraceUrls = (evt.args.data.stackTrace || []).map(l => l.url).filter(Boolean);\n\n switch (evt.name) {\n case 'TimerInstall':\n // @ts-expect-error - 'TimerInstall' event means timerId exists.\n timers.set(evt.args.data.timerId, node);\n stackTraceUrls.forEach(url => addDependencyOnUrl(node, url));\n break;\n case 'TimerFire': {\n // @ts-expect-error - 'TimerFire' event means timerId exists.\n const installer = timers.get(evt.args.data.timerId);\n if (!installer || installer.endTime > node.startTime) {\n break;\n }\n installer.addDependent(node);\n break;\n }\n\n case 'InvalidateLayout':\n case 'ScheduleStyleRecalculation':\n addDependencyOnFrame(node, evt.args.data.frame);\n stackTraceUrls.forEach(url => addDependencyOnUrl(node, url));\n break;\n\n case 'EvaluateScript':\n addDependencyOnFrame(node, evt.args.data.frame);\n // @ts-expect-error - 'EvaluateScript' event means argsUrl is defined.\n addDependencyOnUrl(node, argsUrl);\n stackTraceUrls.forEach(url => addDependencyOnUrl(node, url));\n break;\n\n case 'XHRReadyStateChange':\n // Only create the dependency if the request was completed\n // 'XHRReadyStateChange' event means readyState is defined.\n if (evt.args.data.readyState !== 4) {\n break;\n }\n\n // @ts-expect-error - 'XHRReadyStateChange' event means argsUrl is defined.\n addDependencyOnUrl(node, argsUrl);\n stackTraceUrls.forEach(url => addDependencyOnUrl(node, url));\n break;\n\n case 'FunctionCall':\n case 'v8.compile':\n addDependencyOnFrame(node, evt.args.data.frame);\n // @ts-expect-error - events mean argsUrl is defined.\n addDependencyOnUrl(node, argsUrl);\n break;\n\n case 'ParseAuthorStyleSheet':\n addDependencyOnFrame(node, evt.args.data.frame);\n // @ts-expect-error - 'ParseAuthorStyleSheet' event means styleSheetUrl is defined.\n addDependencyOnUrl(node, evt.args.data.styleSheetUrl);\n break;\n\n case 'ResourceSendRequest':\n addDependencyOnFrame(node, evt.args.data.frame);\n // @ts-expect-error - 'ResourceSendRequest' event means requestId is defined.\n addDependentNetworkRequest(node, evt.args.data.requestId);\n stackTraceUrls.forEach(url => addDependencyOnUrl(node, url));\n break;\n }\n }\n\n // Nodes starting before the root node cannot depend on it.\n if (node.getNumberOfDependencies() === 0 && node.canDependOn(rootNode)) {\n node.addDependency(rootNode);\n }\n }\n\n // Second pass to prune the graph of short tasks.\n const minimumEvtDur = SIGNIFICANT_DUR_THRESHOLD_MS * 1000;\n let foundFirstLayout = false;\n let foundFirstPaint = false;\n let foundFirstParse = false;\n\n for (const node of cpuNodes) {\n // Don't prune if event is the first ParseHTML/Layout/Paint.\n // See https://github.com/GoogleChrome/lighthouse/issues/9627#issuecomment-526699524 for more.\n let isFirst = false;\n if (!foundFirstLayout && node.childEvents.some(evt => evt.name === 'Layout')) {\n isFirst = foundFirstLayout = true;\n }\n if (!foundFirstPaint && node.childEvents.some(evt => evt.name === 'Paint')) {\n isFirst = foundFirstPaint = true;\n }\n if (!foundFirstParse && node.childEvents.some(evt => evt.name === 'ParseHTML')) {\n isFirst = foundFirstParse = true;\n }\n\n if (isFirst || node.duration >= minimumEvtDur) {\n // Don't prune this node. The task is long / important so it will impact simulation.\n continue;\n }\n\n // Prune the node if it isn't highly connected to minimize graph size. Rewiring the graph\n // here replaces O(M + N) edges with (M * N) edges, which is fine if either M or N is at\n // most 1.\n if (node.getNumberOfDependencies() === 1 || node.getNumberOfDependents() <= 1) {\n PageDependencyGraph.pruneNode(node);\n }\n }\n }\n\n /**\n * Removes the given node from the graph, but retains all paths between its dependencies and\n * dependents.\n */\n static pruneNode(node: Node): void {\n const dependencies = node.getDependencies();\n const dependents = node.getDependents();\n for (const dependency of dependencies) {\n node.removeDependency(dependency);\n for (const dependent of dependents) {\n dependency.addDependent(dependent);\n }\n }\n for (const dependent of dependents) {\n node.removeDependent(dependent);\n }\n }\n\n /**\n * TODO: remove when CDT backend in Lighthouse is gone. Until then, this is a useful debugging tool\n * to find delta between using CDP or the trace to create the network requests.\n *\n * When a test fails using the trace backend, I enabled this debug method and copied the network\n * requests when CDP was used, then when trace is used, and diff'd them. This method helped\n * remove non-logical differences from the comparison (order of properties, slight rounding\n * discrepancies, removing object cycles, etc).\n *\n * When using for a unit test, make sure to do `.only` so you are getting what you expect.\n */\n static debugNormalizeRequests(lanternRequests: Lantern.NetworkRequest[]): void {\n for (const request of lanternRequests) {\n request.rendererStartTime = Math.round(request.rendererStartTime * 1000) / 1000;\n request.networkRequestTime = Math.round(request.networkRequestTime * 1000) / 1000;\n request.responseHeadersEndTime = Math.round(request.responseHeadersEndTime * 1000) / 1000;\n request.networkEndTime = Math.round(request.networkEndTime * 1000) / 1000;\n }\n\n for (const r of lanternRequests) {\n delete r.rawRequest;\n if (r.initiatorRequest) {\n // @ts-expect-error\n r.initiatorRequest = {id: r.initiatorRequest.requestId};\n }\n if (r.redirectDestination) {\n // @ts-expect-error\n r.redirectDestination = {id: r.redirectDestination.requestId};\n }\n if (r.redirectSource) {\n // @ts-expect-error\n r.redirectSource = {id: r.redirectSource.requestId};\n }\n if (r.redirects) {\n // @ts-expect-error\n r.redirects = r.redirects.map(r2 => r2.requestId);\n }\n }\n const requests: Lantern.NetworkRequest[] = lanternRequests\n .map(r => ({\n requestId: r.requestId,\n connectionId: r.connectionId,\n connectionReused: r.connectionReused,\n url: r.url,\n protocol: r.protocol,\n parsedURL: r.parsedURL,\n documentURL: r.documentURL,\n rendererStartTime: r.rendererStartTime,\n networkRequestTime: r.networkRequestTime,\n responseHeadersEndTime: r.responseHeadersEndTime,\n networkEndTime: r.networkEndTime,\n transferSize: r.transferSize,\n resourceSize: r.resourceSize,\n fromDiskCache: r.fromDiskCache,\n fromMemoryCache: r.fromMemoryCache,\n finished: r.finished,\n statusCode: r.statusCode,\n redirectSource: r.redirectSource,\n redirectDestination: r.redirectDestination,\n redirects: r.redirects,\n failed: r.failed,\n initiator: r.initiator,\n timing: r.timing ? {\n requestTime: r.timing.requestTime,\n proxyStart: r.timing.proxyStart,\n proxyEnd: r.timing.proxyEnd,\n dnsStart: r.timing.dnsStart,\n dnsEnd: r.timing.dnsEnd,\n connectStart: r.timing.connectStart,\n connectEnd: r.timing.connectEnd,\n sslStart: r.timing.sslStart,\n sslEnd: r.timing.sslEnd,\n workerStart: r.timing.workerStart,\n workerReady: r.timing.workerReady,\n workerFetchStart: r.timing.workerFetchStart,\n workerRespondWithSettled: r.timing.workerRespondWithSettled,\n sendStart: r.timing.sendStart,\n sendEnd: r.timing.sendEnd,\n pushStart: r.timing.pushStart,\n pushEnd: r.timing.pushEnd,\n receiveHeadersStart: r.timing.receiveHeadersStart,\n receiveHeadersEnd: r.timing.receiveHeadersEnd,\n } :\n r.timing,\n resourceType: r.resourceType,\n mimeType: r.mimeType,\n priority: r.priority,\n initiatorRequest: r.initiatorRequest,\n frameId: r.frameId,\n fromWorker: r.fromWorker,\n isLinkPreload: r.isLinkPreload,\n serverResponseTime: r.serverResponseTime,\n }))\n .filter(r => !r.fromWorker);\n\n const debug = requests;\n // Set breakpoint here.\n // Copy `debug` and compare with https://www.diffchecker.com/text-compare/\n // eslint-disable-next-line no-console\n console.log(debug);\n }\n\n static createGraph(\n mainThreadEvents: Lantern.TraceEvent[], networkRequests: Lantern.NetworkRequest[],\n url: Lantern.Simulation.URL): Node {\n // This is for debugging trace/devtoolslog network records.\n // const debug = PageDependencyGraph.debugNormalizeRequests(networkRequests);\n const networkNodeOutput = PageDependencyGraph.getNetworkNodeOutput(networkRequests);\n const cpuNodes = PageDependencyGraph.getCPUNodes(mainThreadEvents);\n const {requestedUrl, mainDocumentUrl} = url;\n if (!requestedUrl) {\n throw new Core.LanternError('requestedUrl is required to get the root request');\n }\n if (!mainDocumentUrl) {\n throw new Core.LanternError('mainDocumentUrl is required to get the main resource');\n }\n\n const rootRequest = Core.NetworkAnalyzer.findResourceForUrl(networkRequests, requestedUrl);\n if (!rootRequest) {\n throw new Core.LanternError('rootRequest not found');\n }\n const rootNode = networkNodeOutput.idToNodeMap.get(rootRequest.requestId);\n if (!rootNode) {\n throw new Core.LanternError('rootNode not found');\n }\n const mainDocumentRequest = Core.NetworkAnalyzer.findLastDocumentForUrl(networkRequests, mainDocumentUrl);\n if (!mainDocumentRequest) {\n throw new Core.LanternError('mainDocumentRequest not found');\n }\n const mainDocumentNode = networkNodeOutput.idToNodeMap.get(mainDocumentRequest.requestId);\n if (!mainDocumentNode) {\n throw new Core.LanternError('mainDocumentNode not found');\n }\n\n PageDependencyGraph.linkNetworkNodes(rootNode, networkNodeOutput);\n PageDependencyGraph.linkCPUNodes(rootNode, networkNodeOutput, cpuNodes);\n mainDocumentNode.setIsMainDocument(true);\n\n if (NetworkNode.hasCycle(rootNode)) {\n throw new Core.LanternError('Invalid dependency graph created, cycle detected');\n }\n\n return rootNode;\n }\n\n // Unused, but useful for debugging.\n static printGraph(rootNode: Node, widthInCharacters = 100): void {\n function padRight(str: string, target: number, padChar = ' '): string {\n return str + padChar.repeat(Math.max(target - str.length, 0));\n }\n\n const nodes: Node[] = [];\n rootNode.traverse(node => nodes.push(node));\n nodes.sort((a, b) => a.startTime - b.startTime);\n\n const min = nodes[0].startTime;\n const max = nodes.reduce((max, node) => Math.max(max, node.endTime), 0);\n\n const totalTime = max - min;\n const timePerCharacter = totalTime / widthInCharacters;\n nodes.forEach(node => {\n const offset = Math.round((node.startTime - min) / timePerCharacter);\n const length = Math.ceil((node.endTime - node.startTime) / timePerCharacter);\n const bar = padRight('', offset) + padRight('', length, '=');\n\n // @ts-expect-error -- disambiguate displayName from across possible Node types.\n const displayName = node.request ? node.request.url : node.type;\n // eslint-disable-next-line\n console.log(padRight(bar, widthInCharacters), `| ${displayName.slice(0, 30)}`);\n });\n }\n}\n\nexport {PageDependencyGraph};\n"]}
|
|
@@ -431,6 +431,7 @@ class Simulator {
|
|
|
431
431
|
// This is an estimate of wasted time, so we won't be more precise than 10ms.
|
|
432
432
|
return Math.round(wastedMs / 10) * 10;
|
|
433
433
|
}
|
|
434
|
+
// Used by Lighthouse asset-saver
|
|
434
435
|
static get allNodeTimings() {
|
|
435
436
|
return ALL_SIMULATION_NODE_TIMINGS;
|
|
436
437
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Simulator.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/simulation/Simulator.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAG3C,OAAO,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AACvC,OAAO,EAAiD,kBAAkB,EAAC,MAAM,0BAA0B,CAAC;AAC5G,OAAO,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AAOjD,MAAM,iBAAiB,GAAG,SAAS,CAAC,UAAU,CAAC,YAAY,CAAC;AAE5D,6GAA6G;AAC7G,MAAM,mCAAmC,GAAG,EAAE,CAAC;AAC/C,6FAA6F;AAC7F,MAAM,8BAA8B,GAAG,GAAG,CAAC;AAC3C,gHAAgH;AAChH,MAAM,iCAAiC,GAAG,KAAK,CAAC;AAEhD,MAAM,SAAS,GAAG;IAChB,eAAe,EAAE,CAAC;IAClB,YAAY,EAAE,CAAC;IACf,UAAU,EAAE,CAAC;IACb,QAAQ,EAAE,CAAC;CACZ,CAAC;AAEF,MAAM,wBAAwB,GAA6C;IACzE,QAAQ,EAAE,CAAC;IACX,IAAI,EAAE,IAAI;IACV,MAAM,EAAE,GAAG;IACX,GAAG,EAAE,CAAC;IACN,OAAO,EAAE,CAAC;CACX,CAAC;AAEF,MAAM,2BAA2B,GAAG,IAAI,GAAG,EAA+C,CAAC;AAE3F,MAAM,SAAS;IACb,MAAM,CAAC,eAAe,CAAC,QAAqC;QAC1D,MAAM,EAAC,gBAAgB,EAAE,UAAU,EAAE,sBAAsB,EAAE,eAAe,EAAC,GAAG,QAAQ,CAAC;QAEzF,MAAM,OAAO,GAA+B;YAC1C,qBAAqB,EAAE,eAAe,CAAC,qBAAqB;YAC5D,0BAA0B,EAAE,eAAe,CAAC,0BAA0B;YACtE,kBAAkB,EAAE,eAAe,CAAC,UAAU;SAC/C,CAAC;QAEF,oGAAoG;QACpG,2BAA2B;QAC3B,IAAI,sBAAsB,EAAE,CAAC;YAC3B,OAAO,CAAC,qBAAqB,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,sBAAsB,CAAC,qBAAqB,CAAC,CAAC,CAAC;YACtG,OAAO,CAAC,0BAA0B,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,sBAAsB,CAAC,0BAA0B,CAAC,CAAC,CAAC;QAClH,CAAC;QAED,QAAQ,gBAAgB,EAAE,CAAC;YACzB,KAAK,UAAU;gBACb,OAAO,CAAC,GAAG,GAAG,eAAe,CAAC,GAAG,CAAC;gBAClC,OAAO,CAAC,UAAU,GAAG,eAAe,CAAC,UAAU,CAAC;gBAChD,OAAO,CAAC,qBAAqB,GAAG,CAAC,CAAC;gBAClC,OAAO,CAAC,oBAAoB,GAAG,CAAC,CAAC;gBACjC,MAAM;YACR,KAAK,UAAU;gBACb,IAAI,UAAU,EAAE,CAAC;oBACf,OAAO,CAAC,GAAG,GAAG,UAAU,CAAC,gBAAgB,GAAG,SAAS,CAAC,UAAU,CAAC,8BAA8B,CAAC;oBAChG,OAAO,CAAC,UAAU;wBACd,UAAU,CAAC,sBAAsB,GAAG,IAAI,GAAG,SAAS,CAAC,UAAU,CAAC,qCAAqC,CAAC;gBAC5G,CAAC;gBAED,OAAO,CAAC,qBAAqB,GAAG,CAAC,CAAC;gBAClC,OAAO,CAAC,oBAAoB,GAAG,CAAC,CAAC;gBACjC,MAAM;YACR,KAAK,UAAU;gBACb,IAAI,UAAU,EAAE,CAAC;oBACf,OAAO,CAAC,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC;oBAC/B,OAAO,CAAC,UAAU,GAAG,UAAU,CAAC,cAAc,GAAG,IAAI,CAAC;oBACtD,OAAO,CAAC,qBAAqB,GAAG,UAAU,CAAC,qBAAqB,CAAC;gBACnE,CAAC;gBACD,MAAM;YACR;gBACE,+CAA+C;gBAC/C,MAAM;QACV,CAAC;QAED,OAAO,IAAI,SAAS,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAED,OAAO,CAAuC;IAC9C,IAAI,CAAS;IACb,UAAU,CAAS;IACnB,yBAAyB,CAAS;IAClC,qBAAqB,CAAS;IAC9B,oBAAoB,CAAS;IAC7B,6BAA6B,CAAe;IAC5C,WAAW,CAAqB;IAChC,sBAAsB,CAAsB;IAC5C,KAAK,CAAkC;IACvC,GAAG,CAAW;IACd,cAAc,CAAiB;IAE/B,YAAY,OAAoC;QAC9C,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CACxB;YACE,GAAG,EAAE,iBAAiB,CAAC,KAAK;YAC5B,UAAU,EAAE,iBAAiB,CAAC,cAAc,GAAG,IAAI;YACnD,yBAAyB,EAAE,mCAAmC;YAC9D,qBAAqB,EAAE,iBAAiB,CAAC,qBAAqB;YAC9D,oBAAoB,EAAE,8BAA8B;YACpD,qBAAqB,EAAE,IAAI,GAAG,EAAE;YAChC,0BAA0B,EAAE,IAAI,GAAG,EAAE;SACtC,EACD,OAAO,CACV,CAAC;QAEF,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;QAC1C,IAAI,CAAC,yBAAyB,GAAG,IAAI,CAAC,GAAG,CACrC,IAAI,CAAC,GAAG,CACJ,aAAa,CAAC,2BAA2B,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,EACrE,IAAI,CAAC,OAAO,CAAC,yBAAyB,CACrC,EACL,CAAC,CAAC,CAAC;QACP,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC,OAAO,CAAC,qBAAqB,CAAC;QAChE,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC;QAC3F,IAAI,CAAC,6BAA6B,GAAG,EAAE,CAAC;QAExC,mFAAmF;QACnF,IAAI,CAAC,WAAW,GAAG,IAAI,kBAAkB,EAAE,CAAC;QAC5C,IAAI,CAAC,sBAAsB,GAAG,IAAI,GAAG,EAAkB,CAAC;QACxD,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,GAAG,GAAG,IAAI,QAAQ,CAAC,EAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAC,CAAC,CAAC;QAC1C,mBAAmB;QACnB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAE3B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,eAAe,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1D,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YACtC,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,sBAAsB,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;IAED,IAAI,GAAG;QACL,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,wBAAwB,CAAC,KAAiB;QACxC,MAAM,OAAO,GAA6B,EAAE,CAAC;QAC7C,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;YAClC,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;gBAC/C,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,cAAc,GAAG,IAAI,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAClE,CAAC;IAED;;OAEG;IACH,uBAAuB;QACrB,IAAI,CAAC,WAAW,GAAG,IAAI,kBAAkB,EAAE,CAAC;QAC5C,IAAI,CAAC,sBAAsB,GAAG,IAAI,GAAG,EAAE,CAAC;QAExC,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,6BAA6B,GAAG,EAAE,CAAC;QACxC,8FAA8F;QAC9F,oCAAoC;QACpC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7C,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;QAChC,CAAC;IACH,CAAC;IAED,gBAAgB,CAAC,IAAY;QAC3B,OAAO,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpD,CAAC;IAED,sBAAsB,CAAC,IAAgB,EAAE,UAAkB;QACzD,MAAM,iBAAiB,GAAG,SAAS,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAC;QACnE,MAAM,sCAAsC,GAAG,IAAI,CAAC,6BAA6B,CAAC,SAAS,CACvF,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,wBAAwB,CAAC,SAAS,CAAC,GAAG,iBAAiB,CAAC,CAAC;QACpF,MAAM,cAAc,GAAG,sCAAsC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,6BAA6B,CAAC,MAAM,CAAC,CAAC;YAC3C,sCAAsC,CAAC;QAC9G,IAAI,CAAC,6BAA6B,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;QAEnE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACnD,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,IAAI,EAAE,EAAC,UAAU,EAAC,CAAC,CAAC;IACvD,CAAC;IAED,oBAAoB,CAAC,IAAgB,EAAE,SAAiB;QACtD,MAAM,kBAAkB,GAAG,IAAI,CAAC,6BAA6B,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC5E,IAAI,CAAC,6BAA6B,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;QAEjE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAChD,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACjF,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,IAAI,EAAE,EAAC,SAAS,EAAC,CAAC,CAAC;IACpD,CAAC;IAED,kBAAkB,CAAC,IAAgB,EAAE,OAAe,EAAE,gBAAmC;QACvF,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACjF,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,IAAI,EAAE,EAAC,OAAO,EAAE,gBAAgB,EAAC,CAAC,CAAC;QAEjE,6CAA6C;QAC7C,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC;YAC7C,qEAAqE;YACrE,MAAM,YAAY,GAAG,SAAS,CAAC,eAAe,EAAE,CAAC;YACjD,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;gBACvE,SAAS;YACX,CAAC;YAED,gCAAgC;YAChC,IAAI,CAAC,sBAAsB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAED,iBAAiB,CAAC,OAA+B;QAC/C,OAAO,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED,6BAA6B;QAC3B,oEAAoE;QACpE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;IACxD,CAAC;IAED,mBAAmB,CAAC,IAAgB,EAAE,gBAAwB;QAC5D,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;YAC3C,2DAA2D;YAC3D,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3C,IAAI,CAAC,oBAAoB,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;YACpD,CAAC;YAED,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YAC/C,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QAC7C,CAAC;QAED,gGAAgG;QAChG,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,qFAAqF;YACrF,MAAM,sBAAsB,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChE,IAAI,sBAAsB,IAAI,IAAI,CAAC,yBAAyB,EAAE,CAAC;gBAC7D,OAAO;YACT,CAAC;YACD,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACxD,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,OAAO;YACT,CAAC;QACH,CAAC;QAED,IAAI,CAAC,oBAAoB,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;IACpD,CAAC;IAED;;;OAGG;IACH,qBAAqB;QACnB,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACrE,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;YACnB,OAAO;QACT,CAAC;QAED,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,cAAc,CAAC,gBAAgB,EAAE,EAAE,CAAC;YAChE,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED;;OAEG;IACH,qBAAqB,CAAC,IAAgB;QACpC,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;YAC3C,OAAO,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YAC/C,OAAO,IAAI,CAAC,4BAA4B,CAAC,IAAI,CAAC,CAAC;QACjD,CAAC;QACD,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;IAC7C,CAAC;IAED,wBAAwB,CAAC,OAAsB;QAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC3D,MAAM,UAAU,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC;QACvG,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAC1B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,GAAG,IAAI,GAAG,UAAU,CAAC,EAChD,iCAAiC,CACpC,CAAC;QACF,MAAM,oBAAoB,GAAG,aAAa,GAAG,UAAU,CAAC,WAAW,CAAC;QACpE,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,OAAO,EAAE,EAAC,oBAAoB,EAAC,CAAC,CAAC;QAClE,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IAED,4BAA4B,CAAC,WAA8B;QACzD,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC;QACpC,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;QAEnE,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,IAAI,WAAW,CAAC,aAAa,EAAE,CAAC;YAC9B,8EAA8E;YAC9E,yBAAyB;YACzB,8CAA8C;YAC9C,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;YAC3D,WAAW,GAAG,CAAC,GAAG,EAAE,GAAG,QAAQ,GAAG,UAAU,CAAC,WAAW,CAAC;QAC3D,CAAC;aAAM,IAAI,WAAW,CAAC,oBAAoB,EAAE,CAAC;YAC5C,sGAAsG;YACtG,4BAA4B;YAC5B,sEAAsE;YACtE,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;YAC3D,WAAW,GAAG,CAAC,GAAG,EAAE,GAAG,QAAQ,GAAG,UAAU,CAAC,WAAW,CAAC;QAC3D,CAAC;aAAM,CAAC;YACN,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC,kCAAkC,CAAC,OAAO,CAAC,CAAC;YACnF,MAAM,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,sBAAsB,CAAC,OAAO,EAAE;gBACjE,WAAW,EAAE,UAAU,CAAC,SAAS;gBACjC,iBAAiB,EAAE,IAAI;aACxB,CAAC,CAAC;YACH,MAAM,kBAAkB,GAAG,UAAU,CAAC,WAAW,CAAC;YAClD,MAAM,WAAW,GAAG,UAAU,CAAC,qBAAqB,CAChD,OAAO,CAAC,YAAY,GAAG,UAAU,CAAC,eAAe,EACjD,EAAC,kBAAkB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,QAAQ,EAAC,CACzE,CAAC;YAEF,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC;QACxC,CAAC;QAED,MAAM,oBAAoB,GAAG,WAAW,GAAG,UAAU,CAAC,oBAAoB,CAAC;QAC3E,IAAI,CAAC,WAAW,CAAC,mBAAmB,CAAC,WAAW,EAAE,EAAC,oBAAoB,EAAC,CAAC,CAAC;QAC1E,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IAED;;OAEG;IACH,0BAA0B;QACxB,IAAI,WAAW,GAAG,QAAQ,CAAC;QAC3B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC;YACpD,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC;QACxE,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,8BAA8B,CAAC,IAAgB,EAAE,gBAAwB,EAAE,gBAAwB;QACjG,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QACxD,MAAM,UAAU,GAAG,UAAU,CAAC,oBAAoB,KAAK,gBAAgB,CAAC;QAExE,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACpE,IAAI,UAAU,EAAE,CAAC;gBACf,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;YAClD,CAAC;iBAAM,CAAC;gBACN,UAAU,CAAC,WAAW,IAAI,gBAAgB,CAAC;YAC7C,CAAC;YACD,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YAC/C,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,CAAC,CAAC,iBAAiB,IAAI,UAAU,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,qBAAqB,CAAC,CAAC;QACrD,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7B,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC,kCAAkC,CAAC,OAAO,CAAC,CAAC;QACnF,MAAM,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,sBAAsB,CAAC,OAAO,EAAE;YACjE,WAAW,EAAE,UAAU,CAAC,SAAS;YACjC,iBAAiB,EAAE,IAAI;SACxB,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,UAAU,CAAC,qBAAqB,CAChD,OAAO,CAAC,YAAY,GAAG,UAAU,CAAC,eAAe,EACjD;YACE,iBAAiB;YACjB,kBAAkB,EAAE,UAAU,CAAC,WAAW;YAC1C,mBAAmB,EAAE,gBAAgB,GAAG,UAAU,CAAC,oBAAoB;SACxE,CACJ,CAAC;QAEF,UAAU,CAAC,mBAAmB,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC;QAC7D,UAAU,CAAC,4BAA4B,CAAC,WAAW,CAAC,oBAAoB,CAAC,CAAC;QAE1E,IAAI,UAAU,EAAE,CAAC;YACf,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACrC,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,EAAE,WAAW,CAAC,gBAAgB,CAAC,CAAC;QAChF,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,WAAW,IAAI,WAAW,CAAC,WAAW,CAAC;YAClD,UAAU,CAAC,oBAAoB,IAAI,WAAW,CAAC,WAAW,GAAG,gBAAgB,CAAC;YAC9E,UAAU,CAAC,eAAe,IAAI,WAAW,CAAC,eAAe,CAAC;QAC5D,CAAC;IACH,CAAC;IAED,uBAAuB;QAIrB,MAAM,yBAAyB,GAA4C,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YAChH,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;QAEH,yFAAyF;QACzF,yBAAyB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAE1E,2DAA2D;QAC3D,MAAM,iBAAiB,GACnB,yBAAyB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE;YAC/C,OAAO;gBACL,IAAI;gBACJ;oBACE,SAAS,EAAE,MAAM,CAAC,SAAS;oBAC3B,OAAO,EAAE,MAAM,CAAC,OAAO;oBACvB,QAAQ,EAAE,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,SAAS;iBAC5C;aACF,CAAC;QACJ,CAAC,CAAC,CAAC;QAEP,OAAO;YACL,WAAW,EAAE,IAAI,GAAG,CAAC,iBAAiB,CAAC;YACvC,mBAAmB,EAAE,IAAI,GAAG,CAAC,yBAAyB,CAAC;SACxD,CAAC;IACJ,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED;;;;;;;;OAQG;IACH,QAAQ,CAAC,KAAiB,EAAE,OAA0B;QACpD,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACnC,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,kCAAkC,CAAC,CAAC;QAClE,CAAC;QAED,OAAO,GAAG,MAAM,CAAC,MAAM,CACnB;YACE,KAAK,EAAE,SAAS;SACjB,EACD,OAAO,CAAC,CAAC;QAEb,2CAA2C;QAC3C,IAAI,CAAC,GAAG,GAAG,IAAI,QAAQ,CAAC,EAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAC,CAAC,CAAC;QAC1C,IAAI,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC;QACrC,IAAI,CAAC,uBAAuB,EAAE,CAAC;QAE/B,MAAM,oBAAoB,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;QACnE,MAAM,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QAC7D,MAAM,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAEzD,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QACrC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1D,IAAI,gBAAgB,GAAG,CAAC,CAAC;QACzB,IAAI,SAAS,GAAG,CAAC,CAAC;QAElB,qCAAqC;QACrC,IAAI,CAAC,sBAAsB,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;QAExD,sEAAsE;QACtE,OAAO,iBAAiB,CAAC,IAAI,IAAI,eAAe,CAAC,IAAI,EAAE,CAAC;YACtD,gDAAgD;YAChD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,6BAA6B,EAAE,EAAE,CAAC;gBACxD,IAAI,CAAC,mBAAmB,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;YACnD,CAAC;YAED,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;gBAC1B,yEAAyE;gBACzE,mBAAmB;gBACnB,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,wBAAwB,CAAC,CAAC;YACxD,CAAC;YAED,wEAAwE;YACxE,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAE7B,+CAA+C;YAC/C,MAAM,WAAW,GAAG,IAAI,CAAC,0BAA0B,EAAE,CAAC;YACtD,gBAAgB,IAAI,WAAW,CAAC;YAEhC,8EAA8E;YAC9E,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,SAAS,GAAG,MAAM,EAAE,CAAC;gBACxD,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,mCAAmC,CAAC,CAAC;YACnE,CAAC;YAED,SAAS,EAAE,CAAC;YACZ,0DAA0D;YAC1D,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;gBACnC,IAAI,CAAC,8BAA8B,CAAC,IAAI,EAAE,WAAW,EAAE,gBAAgB,CAAC,CAAC;YAC3E,CAAC;QACH,CAAC;QAED,4FAA4F;QAC5F,MAAM,EAAC,WAAW,EAAE,mBAAmB,EAAC,GAAG,IAAI,CAAC,uBAAuB,EAAE,CAAC;QAC1E,2BAA2B,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,IAAI,WAAW,EAAE,mBAAmB,CAAC,CAAC;QAEnF,OAAO;YACL,QAAQ,EAAE,gBAAgB;YAC1B,WAAW;SACZ,CAAC;IACJ,CAAC;IAED,8BAA8B,CAAC,WAAmB;QAChD,MAAM,EAAC,UAAU,EAAE,kBAAkB,EAAC,GAAG,IAAI,CAAC,OAAO,CAAC;QAEtD,+EAA+E;QAC/E,iEAAiE;QACjE,kHAAkH;QAClH,MAAM,aAAa,GAAG,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,UAAU,CAAC;QACzE,IAAI,aAAa,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,CAAC;QACX,CAAC;QAED,MAAM,UAAU,GAAG,WAAW,GAAG,CAAC,CAAC;QACnC,MAAM,QAAQ,GAAG,UAAU,GAAG,aAAa,GAAG,IAAI,CAAC;QAEnD,6EAA6E;QAC7E,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC;IACxC,CAAC;IAED,MAAM,KAAK,cAAc;QACvB,OAAO,2BAA2B,CAAC;IACrC,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,wBAAwB,CAAC,IAAgB;QAC9C,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC,SAAS,CAAC;QACxB,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,GAAG,CAAC,wBAAwB,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC;IAC/F,CAAC;CACF;AAED,OAAO,EAAC,SAAS,EAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Core from '../core/core.js';\nimport * as Graph from '../graph/graph.js';\nimport type * as Lantern from '../types/types.js';\n\nimport {ConnectionPool} from './ConnectionPool.js';\nimport {Constants} from './Constants.js';\nimport {DNSCache} from './DNSCache.js';\nimport {type CompleteNodeTiming, type ConnectionTiming, SimulatorTimingMap} from './SimulationTimingMap.js';\nimport {TCPConnection} from './TCPConnection.js';\n\nexport interface Result<T = Lantern.AnyNetworkObject> {\n timeInMs: number;\n nodeTimings: Map<Graph.Node<T>, Lantern.Simulation.NodeTiming>;\n}\n\nconst defaultThrottling = Constants.throttling.mobileSlow4G;\n\n// see https://cs.chromium.org/search/?q=kDefaultMaxNumDelayableRequestsPerClient&sq=package:chromium&type=cs\nconst DEFAULT_MAXIMUM_CONCURRENT_REQUESTS = 10;\n// layout tasks tend to be less CPU-bound and do not experience the same increase in duration\nconst DEFAULT_LAYOUT_TASK_MULTIPLIER = 0.5;\n// if a task takes more than 10 seconds it's usually a sign it isn't actually CPU bound and we're overestimating\nconst DEFAULT_MAXIMUM_CPU_TASK_DURATION = 10000;\n\nconst NodeState = {\n NotReadyToStart: 0,\n ReadyToStart: 1,\n InProgress: 2,\n Complete: 3,\n};\n\nconst PriorityStartTimePenalty: Record<Lantern.ResourcePriority, number> = {\n VeryHigh: 0,\n High: 0.25,\n Medium: 0.5,\n Low: 1,\n VeryLow: 2,\n};\n\nconst ALL_SIMULATION_NODE_TIMINGS = new Map<string, Map<Graph.Node, CompleteNodeTiming>>();\n\nclass Simulator<T = Lantern.AnyNetworkObject> {\n static createSimulator(settings: Lantern.Simulation.Settings): Simulator {\n const {throttlingMethod, throttling, precomputedLanternData, networkAnalysis} = settings;\n\n const options: Lantern.Simulation.Options = {\n additionalRttByOrigin: networkAnalysis.additionalRttByOrigin,\n serverResponseTimeByOrigin: networkAnalysis.serverResponseTimeByOrigin,\n observedThroughput: networkAnalysis.throughput,\n };\n\n // If we have precomputed lantern data, overwrite our observed estimates and use precomputed instead\n // for increased stability.\n if (precomputedLanternData) {\n options.additionalRttByOrigin = new Map(Object.entries(precomputedLanternData.additionalRttByOrigin));\n options.serverResponseTimeByOrigin = new Map(Object.entries(precomputedLanternData.serverResponseTimeByOrigin));\n }\n\n switch (throttlingMethod) {\n case 'provided':\n options.rtt = networkAnalysis.rtt;\n options.throughput = networkAnalysis.throughput;\n options.cpuSlowdownMultiplier = 1;\n options.layoutTaskMultiplier = 1;\n break;\n case 'devtools':\n if (throttling) {\n options.rtt = throttling.requestLatencyMs / Constants.throttling.DEVTOOLS_RTT_ADJUSTMENT_FACTOR;\n options.throughput =\n throttling.downloadThroughputKbps * 1024 / Constants.throttling.DEVTOOLS_THROUGHPUT_ADJUSTMENT_FACTOR;\n }\n\n options.cpuSlowdownMultiplier = 1;\n options.layoutTaskMultiplier = 1;\n break;\n case 'simulate':\n if (throttling) {\n options.rtt = throttling.rttMs;\n options.throughput = throttling.throughputKbps * 1024;\n options.cpuSlowdownMultiplier = throttling.cpuSlowdownMultiplier;\n }\n break;\n default:\n // intentionally fallback to simulator defaults\n break;\n }\n\n return new Simulator(options);\n }\n\n options: Required<Lantern.Simulation.Options>;\n _rtt: number;\n throughput: number;\n maximumConcurrentRequests: number;\n cpuSlowdownMultiplier: number;\n layoutTaskMultiplier: number;\n cachedNodeListByStartPosition: Graph.Node[];\n nodeTimings: SimulatorTimingMap;\n numberInProgressByType: Map<string, number>;\n nodes: Record<number, Set<Graph.Node>>;\n dns: DNSCache;\n connectionPool: ConnectionPool;\n\n constructor(options?: Lantern.Simulation.Options) {\n this.options = Object.assign(\n {\n rtt: defaultThrottling.rttMs,\n throughput: defaultThrottling.throughputKbps * 1024,\n maximumConcurrentRequests: DEFAULT_MAXIMUM_CONCURRENT_REQUESTS,\n cpuSlowdownMultiplier: defaultThrottling.cpuSlowdownMultiplier,\n layoutTaskMultiplier: DEFAULT_LAYOUT_TASK_MULTIPLIER,\n additionalRttByOrigin: new Map(),\n serverResponseTimeByOrigin: new Map(),\n },\n options,\n );\n\n this._rtt = this.options.rtt;\n this.throughput = this.options.throughput;\n this.maximumConcurrentRequests = Math.max(\n Math.min(\n TCPConnection.maximumSaturatedConnections(this._rtt, this.throughput),\n this.options.maximumConcurrentRequests,\n ),\n 1);\n this.cpuSlowdownMultiplier = this.options.cpuSlowdownMultiplier;\n this.layoutTaskMultiplier = this.cpuSlowdownMultiplier * this.options.layoutTaskMultiplier;\n this.cachedNodeListByStartPosition = [];\n\n // Properties reset on every `.simulate` call but duplicated here for type checking\n this.nodeTimings = new SimulatorTimingMap();\n this.numberInProgressByType = new Map<string, number>();\n this.nodes = {};\n this.dns = new DNSCache({rtt: this._rtt});\n // @ts-expect-error\n this.connectionPool = null;\n\n if (!Number.isFinite(this._rtt)) {\n throw new Core.LanternError(`Invalid rtt ${this._rtt}`);\n }\n if (!Number.isFinite(this.throughput)) {\n throw new Core.LanternError(`Invalid throughput ${this.throughput}`);\n }\n }\n\n get rtt(): number {\n return this._rtt;\n }\n\n initializeConnectionPool(graph: Graph.Node): void {\n const records: Lantern.NetworkRequest[] = [];\n graph.getRootNode().traverse(node => {\n if (node.type === Graph.BaseNode.types.NETWORK) {\n records.push(node.request);\n }\n });\n\n this.connectionPool = new ConnectionPool(records, this.options);\n }\n\n /**\n * Initializes the various state data structures such _nodeTimings and the _node Sets by state.\n */\n initializeAuxiliaryData(): void {\n this.nodeTimings = new SimulatorTimingMap();\n this.numberInProgressByType = new Map();\n\n this.nodes = {};\n this.cachedNodeListByStartPosition = [];\n // NOTE: We don't actually need *all* of these sets, but the clarity that each node progresses\n // through the system is quite nice.\n for (const state of Object.values(NodeState)) {\n this.nodes[state] = new Set();\n }\n }\n\n numberInProgress(type: string): number {\n return this.numberInProgressByType.get(type) || 0;\n }\n\n markNodeAsReadyToStart(node: Graph.Node, queuedTime: number): void {\n const nodeStartPosition = Simulator.computeNodeStartPosition(node);\n const firstNodeIndexWithGreaterStartPosition = this.cachedNodeListByStartPosition.findIndex(\n candidate => Simulator.computeNodeStartPosition(candidate) > nodeStartPosition);\n const insertionIndex = firstNodeIndexWithGreaterStartPosition === -1 ? this.cachedNodeListByStartPosition.length :\n firstNodeIndexWithGreaterStartPosition;\n this.cachedNodeListByStartPosition.splice(insertionIndex, 0, node);\n\n this.nodes[NodeState.ReadyToStart].add(node);\n this.nodes[NodeState.NotReadyToStart].delete(node);\n this.nodeTimings.setReadyToStart(node, {queuedTime});\n }\n\n markNodeAsInProgress(node: Graph.Node, startTime: number): void {\n const indexOfNodeToStart = this.cachedNodeListByStartPosition.indexOf(node);\n this.cachedNodeListByStartPosition.splice(indexOfNodeToStart, 1);\n\n this.nodes[NodeState.InProgress].add(node);\n this.nodes[NodeState.ReadyToStart].delete(node);\n this.numberInProgressByType.set(node.type, this.numberInProgress(node.type) + 1);\n this.nodeTimings.setInProgress(node, {startTime});\n }\n\n markNodeAsComplete(node: Graph.Node, endTime: number, connectionTiming?: ConnectionTiming): void {\n this.nodes[NodeState.Complete].add(node);\n this.nodes[NodeState.InProgress].delete(node);\n this.numberInProgressByType.set(node.type, this.numberInProgress(node.type) - 1);\n this.nodeTimings.setCompleted(node, {endTime, connectionTiming});\n\n // Try to add all its dependents to the queue\n for (const dependent of node.getDependents()) {\n // Skip dependent node if one of its dependencies hasn't finished yet\n const dependencies = dependent.getDependencies();\n if (dependencies.some(dep => !this.nodes[NodeState.Complete].has(dep))) {\n continue;\n }\n\n // Otherwise add it to the queue\n this.markNodeAsReadyToStart(dependent, endTime);\n }\n }\n\n acquireConnection(request: Lantern.NetworkRequest): TCPConnection|null {\n return this.connectionPool.acquire(request);\n }\n\n getNodesSortedByStartPosition(): Graph.Node[] {\n // Make a copy so we don't skip nodes due to concurrent modification\n return Array.from(this.cachedNodeListByStartPosition);\n }\n\n startNodeIfPossible(node: Graph.Node, totalElapsedTime: number): void {\n if (node.type === Graph.BaseNode.types.CPU) {\n // Start a CPU task if there's no other CPU task in process\n if (this.numberInProgress(node.type) === 0) {\n this.markNodeAsInProgress(node, totalElapsedTime);\n }\n\n return;\n }\n\n if (node.type !== Graph.BaseNode.types.NETWORK) {\n throw new Core.LanternError('Unsupported');\n }\n\n // If a network request is connectionless, we can always start it, so skip the connection checks\n if (!node.isConnectionless) {\n // Start a network request if we're not at max requests and a connection is available\n const numberOfActiveRequests = this.numberInProgress(node.type);\n if (numberOfActiveRequests >= this.maximumConcurrentRequests) {\n return;\n }\n const connection = this.acquireConnection(node.request);\n if (!connection) {\n return;\n }\n }\n\n this.markNodeAsInProgress(node, totalElapsedTime);\n }\n\n /**\n * Updates each connection in use with the available throughput based on the number of network requests\n * currently in flight.\n */\n updateNetworkCapacity(): void {\n const inFlight = this.numberInProgress(Graph.BaseNode.types.NETWORK);\n if (inFlight === 0) {\n return;\n }\n\n for (const connection of this.connectionPool.connectionsInUse()) {\n connection.setThroughput(this.throughput / inFlight);\n }\n }\n\n /**\n * Estimates the number of milliseconds remaining given current conditions before the node is complete.\n */\n estimateTimeRemaining(node: Graph.Node): number {\n if (node.type === Graph.BaseNode.types.CPU) {\n return this.estimateCPUTimeRemaining(node);\n }\n if (node.type === Graph.BaseNode.types.NETWORK) {\n return this.estimateNetworkTimeRemaining(node);\n }\n throw new Core.LanternError('Unsupported');\n }\n\n estimateCPUTimeRemaining(cpuNode: Graph.CPUNode): number {\n const timingData = this.nodeTimings.getCpuStarted(cpuNode);\n const multiplier = cpuNode.didPerformLayout() ? this.layoutTaskMultiplier : this.cpuSlowdownMultiplier;\n const totalDuration = Math.min(\n Math.round(cpuNode.duration / 1000 * multiplier),\n DEFAULT_MAXIMUM_CPU_TASK_DURATION,\n );\n const estimatedTimeElapsed = totalDuration - timingData.timeElapsed;\n this.nodeTimings.setCpuEstimated(cpuNode, {estimatedTimeElapsed});\n return estimatedTimeElapsed;\n }\n\n estimateNetworkTimeRemaining(networkNode: Graph.NetworkNode): number {\n const request = networkNode.request;\n const timingData = this.nodeTimings.getNetworkStarted(networkNode);\n\n let timeElapsed = 0;\n if (networkNode.fromDiskCache) {\n // Rough access time for seeking to location on disk and reading sequentially.\n // 8ms per seek + 20ms/MB\n // @see http://norvig.com/21-days.html#answers\n const sizeInMb = (request.resourceSize || 0) / 1024 / 1024;\n timeElapsed = 8 + 20 * sizeInMb - timingData.timeElapsed;\n } else if (networkNode.isNonNetworkProtocol) {\n // Estimates for the overhead of a data URL in Chromium and the decoding time for base64-encoded data.\n // 2ms per request + 10ms/MB\n // @see traces on https://dopiaza.org/tools/datauri/examples/index.php\n const sizeInMb = (request.resourceSize || 0) / 1024 / 1024;\n timeElapsed = 2 + 10 * sizeInMb - timingData.timeElapsed;\n } else {\n const connection = this.connectionPool.acquireActiveConnectionFromRequest(request);\n const dnsResolutionTime = this.dns.getTimeUntilResolution(request, {\n requestedAt: timingData.startTime,\n shouldUpdateCache: true,\n });\n const timeAlreadyElapsed = timingData.timeElapsed;\n const calculation = connection.simulateDownloadUntil(\n request.transferSize - timingData.bytesDownloaded,\n {timeAlreadyElapsed, dnsResolutionTime, maximumTimeToElapse: Infinity},\n );\n\n timeElapsed = calculation.timeElapsed;\n }\n\n const estimatedTimeElapsed = timeElapsed + timingData.timeElapsedOvershoot;\n this.nodeTimings.setNetworkEstimated(networkNode, {estimatedTimeElapsed});\n return estimatedTimeElapsed;\n }\n\n /**\n * Computes and returns the minimum estimated completion time of the nodes currently in progress.\n */\n findNextNodeCompletionTime(): number {\n let minimumTime = Infinity;\n for (const node of this.nodes[NodeState.InProgress]) {\n minimumTime = Math.min(minimumTime, this.estimateTimeRemaining(node));\n }\n\n return minimumTime;\n }\n\n /**\n * Given a time period, computes the progress toward completion that the node made during that time.\n */\n updateProgressMadeInTimePeriod(node: Graph.Node, timePeriodLength: number, totalElapsedTime: number): void {\n const timingData = this.nodeTimings.getInProgress(node);\n const isFinished = timingData.estimatedTimeElapsed === timePeriodLength;\n\n if (node.type === Graph.BaseNode.types.CPU || node.isConnectionless) {\n if (isFinished) {\n this.markNodeAsComplete(node, totalElapsedTime);\n } else {\n timingData.timeElapsed += timePeriodLength;\n }\n return;\n }\n\n if (node.type !== Graph.BaseNode.types.NETWORK) {\n throw new Core.LanternError('Unsupported');\n }\n if (!('bytesDownloaded' in timingData)) {\n throw new Core.LanternError('Invalid timing data');\n }\n\n const request = node.request;\n const connection = this.connectionPool.acquireActiveConnectionFromRequest(request);\n const dnsResolutionTime = this.dns.getTimeUntilResolution(request, {\n requestedAt: timingData.startTime,\n shouldUpdateCache: true,\n });\n const calculation = connection.simulateDownloadUntil(\n request.transferSize - timingData.bytesDownloaded,\n {\n dnsResolutionTime,\n timeAlreadyElapsed: timingData.timeElapsed,\n maximumTimeToElapse: timePeriodLength - timingData.timeElapsedOvershoot,\n },\n );\n\n connection.setCongestionWindow(calculation.congestionWindow);\n connection.setH2OverflowBytesDownloaded(calculation.extraBytesDownloaded);\n\n if (isFinished) {\n connection.setWarmed(true);\n this.connectionPool.release(request);\n this.markNodeAsComplete(node, totalElapsedTime, calculation.connectionTiming);\n } else {\n timingData.timeElapsed += calculation.timeElapsed;\n timingData.timeElapsedOvershoot += calculation.timeElapsed - timePeriodLength;\n timingData.bytesDownloaded += calculation.bytesDownloaded;\n }\n }\n\n computeFinalNodeTimings(): {\n nodeTimings: Map<Graph.Node, Lantern.Simulation.NodeTiming>,\n completeNodeTimings: Map<Graph.Node, CompleteNodeTiming>,\n } {\n const completeNodeTimingEntries: Array<[Graph.Node, CompleteNodeTiming]> = this.nodeTimings.getNodes().map(node => {\n return [node, this.nodeTimings.getCompleted(node)];\n });\n\n // Most consumers will want the entries sorted by startTime, so insert them in that order\n completeNodeTimingEntries.sort((a, b) => a[1].startTime - b[1].startTime);\n\n // Trimmed version of type `Lantern.Simulation.NodeTiming`.\n const nodeTimingEntries: Array<[Graph.Node, Lantern.Simulation.NodeTiming]> =\n completeNodeTimingEntries.map(([node, timing]) => {\n return [\n node,\n {\n startTime: timing.startTime,\n endTime: timing.endTime,\n duration: timing.endTime - timing.startTime,\n },\n ];\n });\n\n return {\n nodeTimings: new Map(nodeTimingEntries),\n completeNodeTimings: new Map(completeNodeTimingEntries),\n };\n }\n\n getOptions(): Required<Lantern.Simulation.Options> {\n return this.options;\n }\n\n /**\n * Estimates the time taken to process all of the graph's nodes, returns the overall time along with\n * each node annotated by start/end times.\n *\n * Simulator/connection pool are allowed to deviate from what was\n * observed in the trace/devtoolsLog and start requests as soon as they are queued (i.e. do not\n * wait around for a warm connection to be available if the original request was fetched on a warm\n * connection).\n */\n simulate(graph: Graph.Node, options?: {label?: string}): Result<T> {\n if (Graph.BaseNode.hasCycle(graph)) {\n throw new Core.LanternError('Cannot simulate graph with cycle');\n }\n\n options = Object.assign(\n {\n label: undefined,\n },\n options);\n\n // initialize the necessary data containers\n this.dns = new DNSCache({rtt: this._rtt});\n this.initializeConnectionPool(graph);\n this.initializeAuxiliaryData();\n\n const nodesNotReadyToStart = this.nodes[NodeState.NotReadyToStart];\n const nodesReadyToStart = this.nodes[NodeState.ReadyToStart];\n const nodesInProgress = this.nodes[NodeState.InProgress];\n\n const rootNode = graph.getRootNode();\n rootNode.traverse(node => nodesNotReadyToStart.add(node));\n let totalElapsedTime = 0;\n let iteration = 0;\n\n // root node is always ready to start\n this.markNodeAsReadyToStart(rootNode, totalElapsedTime);\n\n // loop as long as we have nodes in the queue or currently in progress\n while (nodesReadyToStart.size || nodesInProgress.size) {\n // move all possible queued nodes to in progress\n for (const node of this.getNodesSortedByStartPosition()) {\n this.startNodeIfPossible(node, totalElapsedTime);\n }\n\n if (!nodesInProgress.size) {\n // Interplay between fromDiskCache and connectionReused can be incorrect,\n // have to give up.\n throw new Core.LanternError('Failed to start a node');\n }\n\n // set the available throughput for all connections based on # in-flight\n this.updateNetworkCapacity();\n\n // find the time that the next node will finish\n const minimumTime = this.findNextNodeCompletionTime();\n totalElapsedTime += minimumTime;\n\n // While this is no longer strictly necessary, it's always better than hanging\n if (!Number.isFinite(minimumTime) || iteration > 100000) {\n throw new Core.LanternError('Simulation failed, depth exceeded');\n }\n\n iteration++;\n // update how far each node will progress until that point\n for (const node of nodesInProgress) {\n this.updateProgressMadeInTimePeriod(node, minimumTime, totalElapsedTime);\n }\n }\n\n // `nodeTimings` are used for simulator consumers, `completeNodeTimings` kept for debugging.\n const {nodeTimings, completeNodeTimings} = this.computeFinalNodeTimings();\n ALL_SIMULATION_NODE_TIMINGS.set(options.label || 'unlabeled', completeNodeTimings);\n\n return {\n timeInMs: totalElapsedTime,\n nodeTimings,\n };\n }\n\n computeWastedMsFromWastedBytes(wastedBytes: number): number {\n const {throughput, observedThroughput} = this.options;\n\n // https://github.com/GoogleChrome/lighthouse/pull/13323#issuecomment-962031709\n // 0 throughput means the no (additional) throttling is expected.\n // This is common for desktop + devtools throttling where throttling is additive and we don't want any additional.\n const bitsPerSecond = throughput === 0 ? observedThroughput : throughput;\n if (bitsPerSecond === 0) {\n return 0;\n }\n\n const wastedBits = wastedBytes * 8;\n const wastedMs = wastedBits / bitsPerSecond * 1000;\n\n // This is an estimate of wasted time, so we won't be more precise than 10ms.\n return Math.round(wastedMs / 10) * 10;\n }\n\n static get allNodeTimings(): Map<string, Map<Graph.Node, CompleteNodeTiming>> {\n return ALL_SIMULATION_NODE_TIMINGS;\n }\n\n /**\n * We attempt to start nodes by their observed start time using the request priority as a tie breaker.\n * When simulating, just because a low priority image started 5ms before a high priority image doesn't mean\n * it would have happened like that when the network was slower.\n */\n static computeNodeStartPosition(node: Graph.Node): number {\n if (node.type === 'cpu') {\n return node.startTime;\n }\n return node.startTime + (PriorityStartTimePenalty[node.request.priority] * 1000 * 1000 || 0);\n }\n}\n\nexport {Simulator};\n"]}
|
|
1
|
+
{"version":3,"file":"Simulator.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/simulation/Simulator.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Core from '../core/core.js';\nimport * as Graph from '../graph/graph.js';\nimport type * as Lantern from '../types/types.js';\n\nimport {ConnectionPool} from './ConnectionPool.js';\nimport {Constants} from './Constants.js';\nimport {DNSCache} from './DNSCache.js';\nimport {type CompleteNodeTiming, type ConnectionTiming, SimulatorTimingMap} from './SimulationTimingMap.js';\nimport {TCPConnection} from './TCPConnection.js';\n\nexport interface Result<T = Lantern.AnyNetworkObject> {\n timeInMs: number;\n nodeTimings: Map<Graph.Node<T>, Lantern.Simulation.NodeTiming>;\n}\n\nconst defaultThrottling = Constants.throttling.mobileSlow4G;\n\n// see https://cs.chromium.org/search/?q=kDefaultMaxNumDelayableRequestsPerClient&sq=package:chromium&type=cs\nconst DEFAULT_MAXIMUM_CONCURRENT_REQUESTS = 10;\n// layout tasks tend to be less CPU-bound and do not experience the same increase in duration\nconst DEFAULT_LAYOUT_TASK_MULTIPLIER = 0.5;\n// if a task takes more than 10 seconds it's usually a sign it isn't actually CPU bound and we're overestimating\nconst DEFAULT_MAXIMUM_CPU_TASK_DURATION = 10000;\n\nconst NodeState = {\n NotReadyToStart: 0,\n ReadyToStart: 1,\n InProgress: 2,\n Complete: 3,\n};\n\nconst PriorityStartTimePenalty: Record<Lantern.ResourcePriority, number> = {\n VeryHigh: 0,\n High: 0.25,\n Medium: 0.5,\n Low: 1,\n VeryLow: 2,\n};\n\nconst ALL_SIMULATION_NODE_TIMINGS = new Map<string, Map<Graph.Node, CompleteNodeTiming>>();\n\nclass Simulator<T = Lantern.AnyNetworkObject> {\n static createSimulator(settings: Lantern.Simulation.Settings): Simulator {\n const {throttlingMethod, throttling, precomputedLanternData, networkAnalysis} = settings;\n\n const options: Lantern.Simulation.Options = {\n additionalRttByOrigin: networkAnalysis.additionalRttByOrigin,\n serverResponseTimeByOrigin: networkAnalysis.serverResponseTimeByOrigin,\n observedThroughput: networkAnalysis.throughput,\n };\n\n // If we have precomputed lantern data, overwrite our observed estimates and use precomputed instead\n // for increased stability.\n if (precomputedLanternData) {\n options.additionalRttByOrigin = new Map(Object.entries(precomputedLanternData.additionalRttByOrigin));\n options.serverResponseTimeByOrigin = new Map(Object.entries(precomputedLanternData.serverResponseTimeByOrigin));\n }\n\n switch (throttlingMethod) {\n case 'provided':\n options.rtt = networkAnalysis.rtt;\n options.throughput = networkAnalysis.throughput;\n options.cpuSlowdownMultiplier = 1;\n options.layoutTaskMultiplier = 1;\n break;\n case 'devtools':\n if (throttling) {\n options.rtt = throttling.requestLatencyMs / Constants.throttling.DEVTOOLS_RTT_ADJUSTMENT_FACTOR;\n options.throughput =\n throttling.downloadThroughputKbps * 1024 / Constants.throttling.DEVTOOLS_THROUGHPUT_ADJUSTMENT_FACTOR;\n }\n\n options.cpuSlowdownMultiplier = 1;\n options.layoutTaskMultiplier = 1;\n break;\n case 'simulate':\n if (throttling) {\n options.rtt = throttling.rttMs;\n options.throughput = throttling.throughputKbps * 1024;\n options.cpuSlowdownMultiplier = throttling.cpuSlowdownMultiplier;\n }\n break;\n default:\n // intentionally fallback to simulator defaults\n break;\n }\n\n return new Simulator(options);\n }\n\n options: Required<Lantern.Simulation.Options>;\n _rtt: number;\n throughput: number;\n maximumConcurrentRequests: number;\n cpuSlowdownMultiplier: number;\n layoutTaskMultiplier: number;\n cachedNodeListByStartPosition: Graph.Node[];\n nodeTimings: SimulatorTimingMap;\n numberInProgressByType: Map<string, number>;\n nodes: Record<number, Set<Graph.Node>>;\n dns: DNSCache;\n connectionPool: ConnectionPool;\n\n constructor(options?: Lantern.Simulation.Options) {\n this.options = Object.assign(\n {\n rtt: defaultThrottling.rttMs,\n throughput: defaultThrottling.throughputKbps * 1024,\n maximumConcurrentRequests: DEFAULT_MAXIMUM_CONCURRENT_REQUESTS,\n cpuSlowdownMultiplier: defaultThrottling.cpuSlowdownMultiplier,\n layoutTaskMultiplier: DEFAULT_LAYOUT_TASK_MULTIPLIER,\n additionalRttByOrigin: new Map(),\n serverResponseTimeByOrigin: new Map(),\n },\n options,\n );\n\n this._rtt = this.options.rtt;\n this.throughput = this.options.throughput;\n this.maximumConcurrentRequests = Math.max(\n Math.min(\n TCPConnection.maximumSaturatedConnections(this._rtt, this.throughput),\n this.options.maximumConcurrentRequests,\n ),\n 1);\n this.cpuSlowdownMultiplier = this.options.cpuSlowdownMultiplier;\n this.layoutTaskMultiplier = this.cpuSlowdownMultiplier * this.options.layoutTaskMultiplier;\n this.cachedNodeListByStartPosition = [];\n\n // Properties reset on every `.simulate` call but duplicated here for type checking\n this.nodeTimings = new SimulatorTimingMap();\n this.numberInProgressByType = new Map<string, number>();\n this.nodes = {};\n this.dns = new DNSCache({rtt: this._rtt});\n // @ts-expect-error\n this.connectionPool = null;\n\n if (!Number.isFinite(this._rtt)) {\n throw new Core.LanternError(`Invalid rtt ${this._rtt}`);\n }\n if (!Number.isFinite(this.throughput)) {\n throw new Core.LanternError(`Invalid throughput ${this.throughput}`);\n }\n }\n\n get rtt(): number {\n return this._rtt;\n }\n\n initializeConnectionPool(graph: Graph.Node): void {\n const records: Lantern.NetworkRequest[] = [];\n graph.getRootNode().traverse(node => {\n if (node.type === Graph.BaseNode.types.NETWORK) {\n records.push(node.request);\n }\n });\n\n this.connectionPool = new ConnectionPool(records, this.options);\n }\n\n /**\n * Initializes the various state data structures such _nodeTimings and the _node Sets by state.\n */\n initializeAuxiliaryData(): void {\n this.nodeTimings = new SimulatorTimingMap();\n this.numberInProgressByType = new Map();\n\n this.nodes = {};\n this.cachedNodeListByStartPosition = [];\n // NOTE: We don't actually need *all* of these sets, but the clarity that each node progresses\n // through the system is quite nice.\n for (const state of Object.values(NodeState)) {\n this.nodes[state] = new Set();\n }\n }\n\n numberInProgress(type: string): number {\n return this.numberInProgressByType.get(type) || 0;\n }\n\n markNodeAsReadyToStart(node: Graph.Node, queuedTime: number): void {\n const nodeStartPosition = Simulator.computeNodeStartPosition(node);\n const firstNodeIndexWithGreaterStartPosition = this.cachedNodeListByStartPosition.findIndex(\n candidate => Simulator.computeNodeStartPosition(candidate) > nodeStartPosition);\n const insertionIndex = firstNodeIndexWithGreaterStartPosition === -1 ? this.cachedNodeListByStartPosition.length :\n firstNodeIndexWithGreaterStartPosition;\n this.cachedNodeListByStartPosition.splice(insertionIndex, 0, node);\n\n this.nodes[NodeState.ReadyToStart].add(node);\n this.nodes[NodeState.NotReadyToStart].delete(node);\n this.nodeTimings.setReadyToStart(node, {queuedTime});\n }\n\n markNodeAsInProgress(node: Graph.Node, startTime: number): void {\n const indexOfNodeToStart = this.cachedNodeListByStartPosition.indexOf(node);\n this.cachedNodeListByStartPosition.splice(indexOfNodeToStart, 1);\n\n this.nodes[NodeState.InProgress].add(node);\n this.nodes[NodeState.ReadyToStart].delete(node);\n this.numberInProgressByType.set(node.type, this.numberInProgress(node.type) + 1);\n this.nodeTimings.setInProgress(node, {startTime});\n }\n\n markNodeAsComplete(node: Graph.Node, endTime: number, connectionTiming?: ConnectionTiming): void {\n this.nodes[NodeState.Complete].add(node);\n this.nodes[NodeState.InProgress].delete(node);\n this.numberInProgressByType.set(node.type, this.numberInProgress(node.type) - 1);\n this.nodeTimings.setCompleted(node, {endTime, connectionTiming});\n\n // Try to add all its dependents to the queue\n for (const dependent of node.getDependents()) {\n // Skip dependent node if one of its dependencies hasn't finished yet\n const dependencies = dependent.getDependencies();\n if (dependencies.some(dep => !this.nodes[NodeState.Complete].has(dep))) {\n continue;\n }\n\n // Otherwise add it to the queue\n this.markNodeAsReadyToStart(dependent, endTime);\n }\n }\n\n acquireConnection(request: Lantern.NetworkRequest): TCPConnection|null {\n return this.connectionPool.acquire(request);\n }\n\n getNodesSortedByStartPosition(): Graph.Node[] {\n // Make a copy so we don't skip nodes due to concurrent modification\n return Array.from(this.cachedNodeListByStartPosition);\n }\n\n startNodeIfPossible(node: Graph.Node, totalElapsedTime: number): void {\n if (node.type === Graph.BaseNode.types.CPU) {\n // Start a CPU task if there's no other CPU task in process\n if (this.numberInProgress(node.type) === 0) {\n this.markNodeAsInProgress(node, totalElapsedTime);\n }\n\n return;\n }\n\n if (node.type !== Graph.BaseNode.types.NETWORK) {\n throw new Core.LanternError('Unsupported');\n }\n\n // If a network request is connectionless, we can always start it, so skip the connection checks\n if (!node.isConnectionless) {\n // Start a network request if we're not at max requests and a connection is available\n const numberOfActiveRequests = this.numberInProgress(node.type);\n if (numberOfActiveRequests >= this.maximumConcurrentRequests) {\n return;\n }\n const connection = this.acquireConnection(node.request);\n if (!connection) {\n return;\n }\n }\n\n this.markNodeAsInProgress(node, totalElapsedTime);\n }\n\n /**\n * Updates each connection in use with the available throughput based on the number of network requests\n * currently in flight.\n */\n updateNetworkCapacity(): void {\n const inFlight = this.numberInProgress(Graph.BaseNode.types.NETWORK);\n if (inFlight === 0) {\n return;\n }\n\n for (const connection of this.connectionPool.connectionsInUse()) {\n connection.setThroughput(this.throughput / inFlight);\n }\n }\n\n /**\n * Estimates the number of milliseconds remaining given current conditions before the node is complete.\n */\n estimateTimeRemaining(node: Graph.Node): number {\n if (node.type === Graph.BaseNode.types.CPU) {\n return this.estimateCPUTimeRemaining(node);\n }\n if (node.type === Graph.BaseNode.types.NETWORK) {\n return this.estimateNetworkTimeRemaining(node);\n }\n throw new Core.LanternError('Unsupported');\n }\n\n estimateCPUTimeRemaining(cpuNode: Graph.CPUNode): number {\n const timingData = this.nodeTimings.getCpuStarted(cpuNode);\n const multiplier = cpuNode.didPerformLayout() ? this.layoutTaskMultiplier : this.cpuSlowdownMultiplier;\n const totalDuration = Math.min(\n Math.round(cpuNode.duration / 1000 * multiplier),\n DEFAULT_MAXIMUM_CPU_TASK_DURATION,\n );\n const estimatedTimeElapsed = totalDuration - timingData.timeElapsed;\n this.nodeTimings.setCpuEstimated(cpuNode, {estimatedTimeElapsed});\n return estimatedTimeElapsed;\n }\n\n estimateNetworkTimeRemaining(networkNode: Graph.NetworkNode): number {\n const request = networkNode.request;\n const timingData = this.nodeTimings.getNetworkStarted(networkNode);\n\n let timeElapsed = 0;\n if (networkNode.fromDiskCache) {\n // Rough access time for seeking to location on disk and reading sequentially.\n // 8ms per seek + 20ms/MB\n // @see http://norvig.com/21-days.html#answers\n const sizeInMb = (request.resourceSize || 0) / 1024 / 1024;\n timeElapsed = 8 + 20 * sizeInMb - timingData.timeElapsed;\n } else if (networkNode.isNonNetworkProtocol) {\n // Estimates for the overhead of a data URL in Chromium and the decoding time for base64-encoded data.\n // 2ms per request + 10ms/MB\n // @see traces on https://dopiaza.org/tools/datauri/examples/index.php\n const sizeInMb = (request.resourceSize || 0) / 1024 / 1024;\n timeElapsed = 2 + 10 * sizeInMb - timingData.timeElapsed;\n } else {\n const connection = this.connectionPool.acquireActiveConnectionFromRequest(request);\n const dnsResolutionTime = this.dns.getTimeUntilResolution(request, {\n requestedAt: timingData.startTime,\n shouldUpdateCache: true,\n });\n const timeAlreadyElapsed = timingData.timeElapsed;\n const calculation = connection.simulateDownloadUntil(\n request.transferSize - timingData.bytesDownloaded,\n {timeAlreadyElapsed, dnsResolutionTime, maximumTimeToElapse: Infinity},\n );\n\n timeElapsed = calculation.timeElapsed;\n }\n\n const estimatedTimeElapsed = timeElapsed + timingData.timeElapsedOvershoot;\n this.nodeTimings.setNetworkEstimated(networkNode, {estimatedTimeElapsed});\n return estimatedTimeElapsed;\n }\n\n /**\n * Computes and returns the minimum estimated completion time of the nodes currently in progress.\n */\n findNextNodeCompletionTime(): number {\n let minimumTime = Infinity;\n for (const node of this.nodes[NodeState.InProgress]) {\n minimumTime = Math.min(minimumTime, this.estimateTimeRemaining(node));\n }\n\n return minimumTime;\n }\n\n /**\n * Given a time period, computes the progress toward completion that the node made during that time.\n */\n updateProgressMadeInTimePeriod(node: Graph.Node, timePeriodLength: number, totalElapsedTime: number): void {\n const timingData = this.nodeTimings.getInProgress(node);\n const isFinished = timingData.estimatedTimeElapsed === timePeriodLength;\n\n if (node.type === Graph.BaseNode.types.CPU || node.isConnectionless) {\n if (isFinished) {\n this.markNodeAsComplete(node, totalElapsedTime);\n } else {\n timingData.timeElapsed += timePeriodLength;\n }\n return;\n }\n\n if (node.type !== Graph.BaseNode.types.NETWORK) {\n throw new Core.LanternError('Unsupported');\n }\n if (!('bytesDownloaded' in timingData)) {\n throw new Core.LanternError('Invalid timing data');\n }\n\n const request = node.request;\n const connection = this.connectionPool.acquireActiveConnectionFromRequest(request);\n const dnsResolutionTime = this.dns.getTimeUntilResolution(request, {\n requestedAt: timingData.startTime,\n shouldUpdateCache: true,\n });\n const calculation = connection.simulateDownloadUntil(\n request.transferSize - timingData.bytesDownloaded,\n {\n dnsResolutionTime,\n timeAlreadyElapsed: timingData.timeElapsed,\n maximumTimeToElapse: timePeriodLength - timingData.timeElapsedOvershoot,\n },\n );\n\n connection.setCongestionWindow(calculation.congestionWindow);\n connection.setH2OverflowBytesDownloaded(calculation.extraBytesDownloaded);\n\n if (isFinished) {\n connection.setWarmed(true);\n this.connectionPool.release(request);\n this.markNodeAsComplete(node, totalElapsedTime, calculation.connectionTiming);\n } else {\n timingData.timeElapsed += calculation.timeElapsed;\n timingData.timeElapsedOvershoot += calculation.timeElapsed - timePeriodLength;\n timingData.bytesDownloaded += calculation.bytesDownloaded;\n }\n }\n\n computeFinalNodeTimings(): {\n nodeTimings: Map<Graph.Node, Lantern.Simulation.NodeTiming>,\n completeNodeTimings: Map<Graph.Node, CompleteNodeTiming>,\n } {\n const completeNodeTimingEntries: Array<[Graph.Node, CompleteNodeTiming]> = this.nodeTimings.getNodes().map(node => {\n return [node, this.nodeTimings.getCompleted(node)];\n });\n\n // Most consumers will want the entries sorted by startTime, so insert them in that order\n completeNodeTimingEntries.sort((a, b) => a[1].startTime - b[1].startTime);\n\n // Trimmed version of type `Lantern.Simulation.NodeTiming`.\n const nodeTimingEntries: Array<[Graph.Node, Lantern.Simulation.NodeTiming]> =\n completeNodeTimingEntries.map(([node, timing]) => {\n return [\n node,\n {\n startTime: timing.startTime,\n endTime: timing.endTime,\n duration: timing.endTime - timing.startTime,\n },\n ];\n });\n\n return {\n nodeTimings: new Map(nodeTimingEntries),\n completeNodeTimings: new Map(completeNodeTimingEntries),\n };\n }\n\n getOptions(): Required<Lantern.Simulation.Options> {\n return this.options;\n }\n\n /**\n * Estimates the time taken to process all of the graph's nodes, returns the overall time along with\n * each node annotated by start/end times.\n *\n * Simulator/connection pool are allowed to deviate from what was\n * observed in the trace/devtoolsLog and start requests as soon as they are queued (i.e. do not\n * wait around for a warm connection to be available if the original request was fetched on a warm\n * connection).\n */\n simulate(graph: Graph.Node, options?: {label?: string}): Result<T> {\n if (Graph.BaseNode.hasCycle(graph)) {\n throw new Core.LanternError('Cannot simulate graph with cycle');\n }\n\n options = Object.assign(\n {\n label: undefined,\n },\n options);\n\n // initialize the necessary data containers\n this.dns = new DNSCache({rtt: this._rtt});\n this.initializeConnectionPool(graph);\n this.initializeAuxiliaryData();\n\n const nodesNotReadyToStart = this.nodes[NodeState.NotReadyToStart];\n const nodesReadyToStart = this.nodes[NodeState.ReadyToStart];\n const nodesInProgress = this.nodes[NodeState.InProgress];\n\n const rootNode = graph.getRootNode();\n rootNode.traverse(node => nodesNotReadyToStart.add(node));\n let totalElapsedTime = 0;\n let iteration = 0;\n\n // root node is always ready to start\n this.markNodeAsReadyToStart(rootNode, totalElapsedTime);\n\n // loop as long as we have nodes in the queue or currently in progress\n while (nodesReadyToStart.size || nodesInProgress.size) {\n // move all possible queued nodes to in progress\n for (const node of this.getNodesSortedByStartPosition()) {\n this.startNodeIfPossible(node, totalElapsedTime);\n }\n\n if (!nodesInProgress.size) {\n // Interplay between fromDiskCache and connectionReused can be incorrect,\n // have to give up.\n throw new Core.LanternError('Failed to start a node');\n }\n\n // set the available throughput for all connections based on # in-flight\n this.updateNetworkCapacity();\n\n // find the time that the next node will finish\n const minimumTime = this.findNextNodeCompletionTime();\n totalElapsedTime += minimumTime;\n\n // While this is no longer strictly necessary, it's always better than hanging\n if (!Number.isFinite(minimumTime) || iteration > 100000) {\n throw new Core.LanternError('Simulation failed, depth exceeded');\n }\n\n iteration++;\n // update how far each node will progress until that point\n for (const node of nodesInProgress) {\n this.updateProgressMadeInTimePeriod(node, minimumTime, totalElapsedTime);\n }\n }\n\n // `nodeTimings` are used for simulator consumers, `completeNodeTimings` kept for debugging.\n const {nodeTimings, completeNodeTimings} = this.computeFinalNodeTimings();\n ALL_SIMULATION_NODE_TIMINGS.set(options.label || 'unlabeled', completeNodeTimings);\n\n return {\n timeInMs: totalElapsedTime,\n nodeTimings,\n };\n }\n\n computeWastedMsFromWastedBytes(wastedBytes: number): number {\n const {throughput, observedThroughput} = this.options;\n\n // https://github.com/GoogleChrome/lighthouse/pull/13323#issuecomment-962031709\n // 0 throughput means the no (additional) throttling is expected.\n // This is common for desktop + devtools throttling where throttling is additive and we don't want any additional.\n const bitsPerSecond = throughput === 0 ? observedThroughput : throughput;\n if (bitsPerSecond === 0) {\n return 0;\n }\n\n const wastedBits = wastedBytes * 8;\n const wastedMs = wastedBits / bitsPerSecond * 1000;\n\n // This is an estimate of wasted time, so we won't be more precise than 10ms.\n return Math.round(wastedMs / 10) * 10;\n }\n\n // Used by Lighthouse asset-saver\n static get allNodeTimings(): Map<string, Map<Graph.Node, CompleteNodeTiming>> {\n return ALL_SIMULATION_NODE_TIMINGS;\n }\n\n /**\n * We attempt to start nodes by their observed start time using the request priority as a tie breaker.\n * When simulating, just because a low priority image started 5ms before a high priority image doesn't mean\n * it would have happened like that when the network was slower.\n */\n static computeNodeStartPosition(node: Graph.Node): number {\n if (node.type === 'cpu') {\n return node.startTime;\n }\n return node.startTime + (PriorityStartTimePenalty[node.request.priority] * 1000 * 1000 || 0);\n }\n}\n\nexport {Simulator};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TCPConnection.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/simulation/TCPConnection.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type {ConnectionTiming} from './SimulationTimingMap.js';\n\ninterface DownloadOptions {\n dnsResolutionTime?: number;\n timeAlreadyElapsed?: number;\n maximumTimeToElapse?: number;\n}\n\ninterface DownloadResults {\n roundTrips: number;\n timeElapsed: number;\n bytesDownloaded: number;\n extraBytesDownloaded: number;\n congestionWindow: number;\n connectionTiming: ConnectionTiming;\n}\n\nconst INITIAL_CONGESTION_WINDOW = 10;\nconst TCP_SEGMENT_SIZE = 1460;\n\nclass TCPConnection {\n warmed: boolean;\n ssl: boolean;\n h2: boolean;\n rtt: number;\n throughput: number;\n serverLatency: number;\n _congestionWindow: number;\n h2OverflowBytesDownloaded: number;\n\n constructor(rtt: number, throughput: number, serverLatency = 0, ssl = true, h2 = false) {\n this.warmed = false;\n this.ssl = ssl;\n this.h2 = h2;\n this.rtt = rtt;\n this.throughput = throughput;\n this.serverLatency = serverLatency;\n this._congestionWindow = INITIAL_CONGESTION_WINDOW;\n this.h2OverflowBytesDownloaded = 0;\n }\n\n static maximumSaturatedConnections(rtt: number, availableThroughput: number): number {\n const roundTripsPerSecond = 1000 / rtt;\n const bytesPerRoundTrip = TCP_SEGMENT_SIZE;\n const bytesPerSecond = roundTripsPerSecond * bytesPerRoundTrip;\n const minimumThroughputRequiredPerRequest = bytesPerSecond * 8;\n return Math.floor(availableThroughput / minimumThroughputRequiredPerRequest);\n }\n\n computeMaximumCongestionWindowInSegments(): number {\n const bytesPerSecond = this.throughput / 8;\n const secondsPerRoundTrip = this.rtt / 1000;\n const bytesPerRoundTrip = bytesPerSecond * secondsPerRoundTrip;\n return Math.floor(bytesPerRoundTrip / TCP_SEGMENT_SIZE);\n }\n\n setThroughput(throughput: number): void {\n this.throughput = throughput;\n }\n\n setCongestionWindow(congestion: number): void {\n this._congestionWindow = congestion;\n }\n\n setWarmed(warmed: boolean): void {\n this.warmed = warmed;\n }\n\n isWarm(): boolean {\n return this.warmed;\n }\n\n isH2(): boolean {\n return this.h2;\n }\n\n get congestionWindow(): number {\n return this._congestionWindow;\n }\n\n /**\n * Sets the number of excess bytes that are available to this connection on future downloads, only\n * applies to H2 connections.\n */\n setH2OverflowBytesDownloaded(bytes: number): void {\n if (!this.h2) {\n return;\n }\n this.h2OverflowBytesDownloaded = bytes;\n }\n\n clone(): TCPConnection {\n return Object.assign(new TCPConnection(this.rtt, this.throughput), this);\n }\n\n /**\n * Simulates a network download of a particular number of bytes over an optional maximum amount of time\n * and returns information about the ending state.\n *\n * See https://hpbn.co/building-blocks-of-tcp/#three-way-handshake and\n * https://hpbn.co/transport-layer-security-tls/#tls-handshake for details.\n */\n simulateDownloadUntil(bytesToDownload: number, options?: DownloadOptions): DownloadResults {\n const {timeAlreadyElapsed = 0, maximumTimeToElapse = Infinity, dnsResolutionTime = 0} = options || {};\n\n if (this.warmed && this.h2) {\n bytesToDownload -= this.h2OverflowBytesDownloaded;\n }\n const twoWayLatency = this.rtt;\n const oneWayLatency = twoWayLatency / 2;\n const maximumCongestionWindow = this.computeMaximumCongestionWindowInSegments();\n\n let handshakeAndRequest = oneWayLatency;\n if (!this.warmed) {\n handshakeAndRequest =\n // DNS lookup\n dnsResolutionTime +\n // SYN\n oneWayLatency +\n // SYN ACK\n oneWayLatency +\n // ACK + initial request\n oneWayLatency +\n // ClientHello/ServerHello assuming TLS False Start is enabled (https://istlsfastyet.com/#server-performance).\n (this.ssl ? twoWayLatency : 0);\n }\n\n let roundTrips = Math.ceil(handshakeAndRequest / twoWayLatency);\n let timeToFirstByte = handshakeAndRequest + this.serverLatency + oneWayLatency;\n if (this.warmed && this.h2) {\n timeToFirstByte = 0;\n }\n\n const timeElapsedForTTFB = Math.max(timeToFirstByte - timeAlreadyElapsed, 0);\n const maximumDownloadTimeToElapse = maximumTimeToElapse - timeElapsedForTTFB;\n\n let congestionWindow = Math.min(this._congestionWindow, maximumCongestionWindow);\n let totalBytesDownloaded = 0;\n if (timeElapsedForTTFB > 0) {\n totalBytesDownloaded = congestionWindow * TCP_SEGMENT_SIZE;\n } else {\n roundTrips = 0;\n }\n\n let downloadTimeElapsed = 0;\n let bytesRemaining = bytesToDownload - totalBytesDownloaded;\n while (bytesRemaining > 0 && downloadTimeElapsed <= maximumDownloadTimeToElapse) {\n roundTrips++;\n downloadTimeElapsed += twoWayLatency;\n congestionWindow = Math.max(Math.min(maximumCongestionWindow, congestionWindow * 2), 1);\n\n const bytesDownloadedInWindow = congestionWindow * TCP_SEGMENT_SIZE;\n totalBytesDownloaded += bytesDownloadedInWindow;\n bytesRemaining -= bytesDownloadedInWindow;\n }\n\n const timeElapsed = timeElapsedForTTFB + downloadTimeElapsed;\n const extraBytesDownloaded = this.h2 ? Math.max(totalBytesDownloaded - bytesToDownload, 0) : 0;\n const bytesDownloaded = Math.max(Math.min(totalBytesDownloaded, bytesToDownload), 0);\n\n let connectionTiming: ConnectionTiming;\n if (!this.warmed) {\n connectionTiming = {\n dnsResolutionTime,\n connectionTime: handshakeAndRequest - dnsResolutionTime,\n sslTime: this.ssl ? twoWayLatency : undefined,\n timeToFirstByte,\n };\n } else if (this.h2) {\n // TODO: timing information currently difficult to model for warm h2 connections.\n connectionTiming = {\n timeToFirstByte,\n };\n } else {\n connectionTiming = {\n connectionTime: handshakeAndRequest,\n timeToFirstByte,\n };\n }\n\n return {\n roundTrips,\n timeElapsed,\n bytesDownloaded,\n extraBytesDownloaded,\n congestionWindow,\n connectionTiming,\n };\n }\n}\n\nexport {TCPConnection};\n"]}
|
|
1
|
+
{"version":3,"file":"TCPConnection.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/simulation/TCPConnection.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAmB7B,MAAM,yBAAyB,GAAG,EAAE,CAAC;AACrC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAE9B,MAAM,aAAa;IACjB,MAAM,CAAU;IAChB,GAAG,CAAU;IACb,EAAE,CAAU;IACZ,GAAG,CAAS;IACZ,UAAU,CAAS;IACnB,aAAa,CAAS;IACtB,iBAAiB,CAAS;IAC1B,yBAAyB,CAAS;IAElC,YAAY,GAAW,EAAE,UAAkB,EAAE,aAAa,GAAG,CAAC,EAAE,GAAG,GAAG,IAAI,EAAE,EAAE,GAAG,KAAK;QACpF,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,iBAAiB,GAAG,yBAAyB,CAAC;QACnD,IAAI,CAAC,yBAAyB,GAAG,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,CAAC,2BAA2B,CAAC,GAAW,EAAE,mBAA2B;QACzE,MAAM,mBAAmB,GAAG,IAAI,GAAG,GAAG,CAAC;QACvC,MAAM,iBAAiB,GAAG,gBAAgB,CAAC;QAC3C,MAAM,cAAc,GAAG,mBAAmB,GAAG,iBAAiB,CAAC;QAC/D,MAAM,mCAAmC,GAAG,cAAc,GAAG,CAAC,CAAC;QAC/D,OAAO,IAAI,CAAC,KAAK,CAAC,mBAAmB,GAAG,mCAAmC,CAAC,CAAC;IAC/E,CAAC;IAED,wCAAwC;QACtC,MAAM,cAAc,GAAG,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QAC3C,MAAM,mBAAmB,GAAG,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;QAC5C,MAAM,iBAAiB,GAAG,cAAc,GAAG,mBAAmB,CAAC;QAC/D,OAAO,IAAI,CAAC,KAAK,CAAC,iBAAiB,GAAG,gBAAgB,CAAC,CAAC;IAC1D,CAAC;IAED,aAAa,CAAC,UAAkB;QAC9B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,mBAAmB,CAAC,UAAkB;QACpC,IAAI,CAAC,iBAAiB,GAAG,UAAU,CAAC;IACtC,CAAC;IAED,SAAS,CAAC,MAAe;QACvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,IAAI;QACF,OAAO,IAAI,CAAC,EAAE,CAAC;IACjB,CAAC;IAED,IAAI,gBAAgB;QAClB,OAAO,IAAI,CAAC,iBAAiB,CAAC;IAChC,CAAC;IAED;;;OAGG;IACH,4BAA4B,CAAC,KAAa;QACxC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QACD,IAAI,CAAC,yBAAyB,GAAG,KAAK,CAAC;IACzC,CAAC;IAED,KAAK;QACH,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,CAAC;IAC3E,CAAC;IAED;;;;;;OAMG;IACH,qBAAqB,CAAC,eAAuB,EAAE,OAAyB;QACtE,MAAM,EAAC,kBAAkB,GAAG,CAAC,EAAE,mBAAmB,GAAG,QAAQ,EAAE,iBAAiB,GAAG,CAAC,EAAC,GAAG,OAAO,IAAI,EAAE,CAAC;QAEtG,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YAC3B,eAAe,IAAI,IAAI,CAAC,yBAAyB,CAAC;QACpD,CAAC;QACD,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC;QAC/B,MAAM,aAAa,GAAG,aAAa,GAAG,CAAC,CAAC;QACxC,MAAM,uBAAuB,GAAG,IAAI,CAAC,wCAAwC,EAAE,CAAC;QAEhF,IAAI,mBAAmB,GAAG,aAAa,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,mBAAmB;gBACf,aAAa;gBACb,iBAAiB;oBACjB,MAAM;oBACN,aAAa;oBACb,UAAU;oBACV,aAAa;oBACb,wBAAwB;oBACxB,aAAa;oBACb,8GAA8G;oBAC9G,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrC,CAAC;QAED,IAAI,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,mBAAmB,GAAG,aAAa,CAAC,CAAC;QAChE,IAAI,eAAe,GAAG,mBAAmB,GAAG,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QAC/E,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YAC3B,eAAe,GAAG,CAAC,CAAC;QACtB,CAAC;QAED,MAAM,kBAAkB,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,GAAG,kBAAkB,EAAE,CAAC,CAAC,CAAC;QAC7E,MAAM,2BAA2B,GAAG,mBAAmB,GAAG,kBAAkB,CAAC;QAE7E,IAAI,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,iBAAiB,EAAE,uBAAuB,CAAC,CAAC;QACjF,IAAI,oBAAoB,GAAG,CAAC,CAAC;QAC7B,IAAI,kBAAkB,GAAG,CAAC,EAAE,CAAC;YAC3B,oBAAoB,GAAG,gBAAgB,GAAG,gBAAgB,CAAC;QAC7D,CAAC;aAAM,CAAC;YACN,UAAU,GAAG,CAAC,CAAC;QACjB,CAAC;QAED,IAAI,mBAAmB,GAAG,CAAC,CAAC;QAC5B,IAAI,cAAc,GAAG,eAAe,GAAG,oBAAoB,CAAC;QAC5D,OAAO,cAAc,GAAG,CAAC,IAAI,mBAAmB,IAAI,2BAA2B,EAAE,CAAC;YAChF,UAAU,EAAE,CAAC;YACb,mBAAmB,IAAI,aAAa,CAAC;YACrC,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,uBAAuB,EAAE,gBAAgB,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAExF,MAAM,uBAAuB,GAAG,gBAAgB,GAAG,gBAAgB,CAAC;YACpE,oBAAoB,IAAI,uBAAuB,CAAC;YAChD,cAAc,IAAI,uBAAuB,CAAC;QAC5C,CAAC;QAED,MAAM,WAAW,GAAG,kBAAkB,GAAG,mBAAmB,CAAC;QAC7D,MAAM,oBAAoB,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,oBAAoB,GAAG,eAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/F,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,oBAAoB,EAAE,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC;QAErF,IAAI,gBAAkC,CAAC;QACvC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,gBAAgB,GAAG;gBACjB,iBAAiB;gBACjB,cAAc,EAAE,mBAAmB,GAAG,iBAAiB;gBACvD,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS;gBAC7C,eAAe;aAChB,CAAC;QACJ,CAAC;aAAM,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACnB,iFAAiF;YACjF,gBAAgB,GAAG;gBACjB,eAAe;aAChB,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,gBAAgB,GAAG;gBACjB,cAAc,EAAE,mBAAmB;gBACnC,eAAe;aAChB,CAAC;QACJ,CAAC;QAED,OAAO;YACL,UAAU;YACV,WAAW;YACX,eAAe;YACf,oBAAoB;YACpB,gBAAgB;YAChB,gBAAgB;SACjB,CAAC;IACJ,CAAC;CACF;AAED,OAAO,EAAC,aAAa,EAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type {ConnectionTiming} from './SimulationTimingMap.js';\n\ninterface DownloadOptions {\n dnsResolutionTime?: number;\n timeAlreadyElapsed?: number;\n maximumTimeToElapse?: number;\n}\n\ninterface DownloadResults {\n roundTrips: number;\n timeElapsed: number;\n bytesDownloaded: number;\n extraBytesDownloaded: number;\n congestionWindow: number;\n connectionTiming: ConnectionTiming;\n}\n\nconst INITIAL_CONGESTION_WINDOW = 10;\nconst TCP_SEGMENT_SIZE = 1460;\n\nclass TCPConnection {\n warmed: boolean;\n ssl: boolean;\n h2: boolean;\n rtt: number;\n throughput: number;\n serverLatency: number;\n _congestionWindow: number;\n h2OverflowBytesDownloaded: number;\n\n constructor(rtt: number, throughput: number, serverLatency = 0, ssl = true, h2 = false) {\n this.warmed = false;\n this.ssl = ssl;\n this.h2 = h2;\n this.rtt = rtt;\n this.throughput = throughput;\n this.serverLatency = serverLatency;\n this._congestionWindow = INITIAL_CONGESTION_WINDOW;\n this.h2OverflowBytesDownloaded = 0;\n }\n\n static maximumSaturatedConnections(rtt: number, availableThroughput: number): number {\n const roundTripsPerSecond = 1000 / rtt;\n const bytesPerRoundTrip = TCP_SEGMENT_SIZE;\n const bytesPerSecond = roundTripsPerSecond * bytesPerRoundTrip;\n const minimumThroughputRequiredPerRequest = bytesPerSecond * 8;\n return Math.floor(availableThroughput / minimumThroughputRequiredPerRequest);\n }\n\n computeMaximumCongestionWindowInSegments(): number {\n const bytesPerSecond = this.throughput / 8;\n const secondsPerRoundTrip = this.rtt / 1000;\n const bytesPerRoundTrip = bytesPerSecond * secondsPerRoundTrip;\n return Math.floor(bytesPerRoundTrip / TCP_SEGMENT_SIZE);\n }\n\n setThroughput(throughput: number): void {\n this.throughput = throughput;\n }\n\n setCongestionWindow(congestion: number): void {\n this._congestionWindow = congestion;\n }\n\n setWarmed(warmed: boolean): void {\n this.warmed = warmed;\n }\n\n isH2(): boolean {\n return this.h2;\n }\n\n get congestionWindow(): number {\n return this._congestionWindow;\n }\n\n /**\n * Sets the number of excess bytes that are available to this connection on future downloads, only\n * applies to H2 connections.\n */\n setH2OverflowBytesDownloaded(bytes: number): void {\n if (!this.h2) {\n return;\n }\n this.h2OverflowBytesDownloaded = bytes;\n }\n\n clone(): TCPConnection {\n return Object.assign(new TCPConnection(this.rtt, this.throughput), this);\n }\n\n /**\n * Simulates a network download of a particular number of bytes over an optional maximum amount of time\n * and returns information about the ending state.\n *\n * See https://hpbn.co/building-blocks-of-tcp/#three-way-handshake and\n * https://hpbn.co/transport-layer-security-tls/#tls-handshake for details.\n */\n simulateDownloadUntil(bytesToDownload: number, options?: DownloadOptions): DownloadResults {\n const {timeAlreadyElapsed = 0, maximumTimeToElapse = Infinity, dnsResolutionTime = 0} = options || {};\n\n if (this.warmed && this.h2) {\n bytesToDownload -= this.h2OverflowBytesDownloaded;\n }\n const twoWayLatency = this.rtt;\n const oneWayLatency = twoWayLatency / 2;\n const maximumCongestionWindow = this.computeMaximumCongestionWindowInSegments();\n\n let handshakeAndRequest = oneWayLatency;\n if (!this.warmed) {\n handshakeAndRequest =\n // DNS lookup\n dnsResolutionTime +\n // SYN\n oneWayLatency +\n // SYN ACK\n oneWayLatency +\n // ACK + initial request\n oneWayLatency +\n // ClientHello/ServerHello assuming TLS False Start is enabled (https://istlsfastyet.com/#server-performance).\n (this.ssl ? twoWayLatency : 0);\n }\n\n let roundTrips = Math.ceil(handshakeAndRequest / twoWayLatency);\n let timeToFirstByte = handshakeAndRequest + this.serverLatency + oneWayLatency;\n if (this.warmed && this.h2) {\n timeToFirstByte = 0;\n }\n\n const timeElapsedForTTFB = Math.max(timeToFirstByte - timeAlreadyElapsed, 0);\n const maximumDownloadTimeToElapse = maximumTimeToElapse - timeElapsedForTTFB;\n\n let congestionWindow = Math.min(this._congestionWindow, maximumCongestionWindow);\n let totalBytesDownloaded = 0;\n if (timeElapsedForTTFB > 0) {\n totalBytesDownloaded = congestionWindow * TCP_SEGMENT_SIZE;\n } else {\n roundTrips = 0;\n }\n\n let downloadTimeElapsed = 0;\n let bytesRemaining = bytesToDownload - totalBytesDownloaded;\n while (bytesRemaining > 0 && downloadTimeElapsed <= maximumDownloadTimeToElapse) {\n roundTrips++;\n downloadTimeElapsed += twoWayLatency;\n congestionWindow = Math.max(Math.min(maximumCongestionWindow, congestionWindow * 2), 1);\n\n const bytesDownloadedInWindow = congestionWindow * TCP_SEGMENT_SIZE;\n totalBytesDownloaded += bytesDownloadedInWindow;\n bytesRemaining -= bytesDownloadedInWindow;\n }\n\n const timeElapsed = timeElapsedForTTFB + downloadTimeElapsed;\n const extraBytesDownloaded = this.h2 ? Math.max(totalBytesDownloaded - bytesToDownload, 0) : 0;\n const bytesDownloaded = Math.max(Math.min(totalBytesDownloaded, bytesToDownload), 0);\n\n let connectionTiming: ConnectionTiming;\n if (!this.warmed) {\n connectionTiming = {\n dnsResolutionTime,\n connectionTime: handshakeAndRequest - dnsResolutionTime,\n sslTime: this.ssl ? twoWayLatency : undefined,\n timeToFirstByte,\n };\n } else if (this.h2) {\n // TODO: timing information currently difficult to model for warm h2 connections.\n connectionTiming = {\n timeToFirstByte,\n };\n } else {\n connectionTiming = {\n connectionTime: handshakeAndRequest,\n timeToFirstByte,\n };\n }\n\n return {\n roundTrips,\n timeElapsed,\n bytesDownloaded,\n extraBytesDownloaded,\n congestionWindow,\n connectionTiming,\n };\n }\n}\n\nexport {TCPConnection};\n"]}
|
|
@@ -2,7 +2,6 @@ import type { Args, ConsoleTimeStamp, Event, PerformanceMark, PerformanceMeasure
|
|
|
2
2
|
export type ExtensionEntryType = 'track-entry' | 'marker';
|
|
3
3
|
export declare const extensionPalette: readonly ["primary", "primary-light", "primary-dark", "secondary", "secondary-light", "secondary-dark", "tertiary", "tertiary-light", "tertiary-dark", "error", "warning"];
|
|
4
4
|
export type ExtensionColorFromPalette = typeof extensionPalette[number];
|
|
5
|
-
export declare function colorIsValid(color: string): boolean;
|
|
6
5
|
export interface ExtensionDataPayloadBase {
|
|
7
6
|
color?: ExtensionColorFromPalette;
|
|
8
7
|
properties?: [string, string][];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Extensions.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/types/Extensions.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAQ7B,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,SAAS;IACT,eAAe;IACf,cAAc;IACd,WAAW;IACX,iBAAiB;IACjB,gBAAgB;IAChB,UAAU;IACV,gBAAgB;IAChB,eAAe;IACf,OAAO;IACP,SAAS;CACD,CAAC;
|
|
1
|
+
{"version":3,"file":"Extensions.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/types/Extensions.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAQ7B,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,SAAS;IACT,eAAe;IACf,cAAc;IACd,WAAW;IACX,iBAAiB;IACjB,gBAAgB;IAChB,UAAU;IACV,gBAAgB;IAChB,eAAe;IACf,OAAO;IACP,SAAS;CACD,CAAC;AAiDX,MAAM,UAAU,wBAAwB,CAAC,OAA4B;IACnE,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,OAA4C;IAEvF,MAAM,QAAQ,GAAG,OAAO,IAAI,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9D,MAAM,cAAc,GAAG,OAAO,CAAC,QAAQ,KAAK,aAAa,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC;IAC5F,OAAO,cAAc,IAAI,QAAQ,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAA4C;IAClF,OAAO,wBAAwB,CAAC,OAAO,CAAC,IAAI,4BAA4B,CAAC,OAAO,CAAC,CAAC;AACpF,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,KAAY;IACpD,OAAO,KAAK,CAAC,GAAG,KAAK,oBAAoB,CAAC;AAC5C,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type {\n Args, ConsoleTimeStamp, Event, PerformanceMark, PerformanceMeasureBegin, Phase, SyntheticBased} from\n './TraceEvents.js';\n\nexport type ExtensionEntryType = 'track-entry'|'marker';\n\nexport const extensionPalette = [\n 'primary',\n 'primary-light',\n 'primary-dark',\n 'secondary',\n 'secondary-light',\n 'secondary-dark',\n 'tertiary',\n 'tertiary-light',\n 'tertiary-dark',\n 'error',\n 'warning',\n] as const;\n\nexport type ExtensionColorFromPalette = typeof extensionPalette[number];\n\nexport interface ExtensionDataPayloadBase {\n color?: ExtensionColorFromPalette;\n properties?: [string, string][];\n tooltipText?: string;\n}\n\nexport type ExtensionDataPayload = ExtensionTrackEntryPayload|ExtensionMarkerPayload;\n\nexport interface ExtensionTrackEntryPayload extends ExtensionDataPayloadBase {\n // Typed as possibly undefined since when no data type is provided\n // the entry is defaulted to a track entry\n dataType?: 'track-entry';\n // The name of the track the entry will be displayed in.\n // Entries intended to be displayed in the same track must contain the\n // same value in this property.\n // If undefined, measurement is added to the Timings track\n track: string;\n // The track group an entry’s track belongs to.\n // Entries intended to be displayed in the same track must contain the\n // same value in this property as well as the same value in the track\n // property.\n trackGroup?: string;\n}\n\nexport interface ExtensionMarkerPayload extends ExtensionDataPayloadBase {\n dataType: 'marker';\n}\n\n/**\n * Synthetic events created for extension tracks.\n */\nexport interface SyntheticExtensionTrackEntry extends\n SyntheticBased<Phase.COMPLETE, PerformanceMeasureBegin|PerformanceMark|ConsoleTimeStamp> {\n args: Args&ExtensionTrackEntryPayload;\n}\n\n/**\n * Synthetic events created for extension marks.\n */\nexport interface SyntheticExtensionMarker extends SyntheticBased<Phase.COMPLETE, PerformanceMark> {\n args: Args&ExtensionMarkerPayload;\n}\n\nexport type SyntheticExtensionEntry = SyntheticExtensionTrackEntry|SyntheticExtensionMarker;\n\nexport function isExtensionPayloadMarker(payload: {dataType?: string}): payload is ExtensionMarkerPayload {\n return payload.dataType === 'marker';\n}\n\nexport function isExtensionPayloadTrackEntry(payload: {track?: string, dataType?: string}):\n payload is ExtensionTrackEntryPayload {\n const hasTrack = 'track' in payload && Boolean(payload.track);\n const validEntryType = payload.dataType === 'track-entry' || payload.dataType === undefined;\n return validEntryType && hasTrack;\n}\n\nexport function isValidExtensionPayload(payload: {track?: string, dataType?: string}): payload is ExtensionDataPayload {\n return isExtensionPayloadMarker(payload) || isExtensionPayloadTrackEntry(payload);\n}\n\nexport function isSyntheticExtensionEntry(entry: Event): entry is SyntheticExtensionEntry {\n return entry.cat === 'devtools.extension';\n}\n\nexport interface ExtensionTrackData {\n // Name of the top level track. If it's a track group then this value\n // has the name of the group, otherwise it has the name of the track.\n name: string;\n isTrackGroup: boolean;\n // If this contains the data of a track group, this property contains\n // the entries of each of the tracks in the the group. If this is a\n // standalone track, then this contains that track's entries only.\n entriesByTrack: {\n [x: string]: SyntheticExtensionTrackEntry[],\n };\n}\n"]}
|
|
@@ -1326,15 +1326,6 @@ export interface DrawFrame extends Instant {
|
|
|
1326
1326
|
};
|
|
1327
1327
|
}
|
|
1328
1328
|
export declare function isDrawFrame(event: Event): event is DrawFrame;
|
|
1329
|
-
export interface LegacyDrawFrameBegin extends Async {
|
|
1330
|
-
name: Name.DRAW_FRAME;
|
|
1331
|
-
ph: Phase.ASYNC_NESTABLE_START;
|
|
1332
|
-
args: Args & {
|
|
1333
|
-
layerTreeId: number;
|
|
1334
|
-
frameSeqId: number;
|
|
1335
|
-
};
|
|
1336
|
-
}
|
|
1337
|
-
export declare function isLegacyTraceEventDrawFrameBegin(event: Event): event is LegacyDrawFrameBegin;
|
|
1338
1329
|
export interface BeginFrame extends Instant {
|
|
1339
1330
|
name: Name.BEGIN_FRAME;
|
|
1340
1331
|
args: Args & {
|
|
@@ -112,9 +112,6 @@ export function isDrawFrame(event) {
|
|
|
112
112
|
// The extra check for INSTANT here is because in the past DrawFrame events had an ASYNC_NESTABLE_START and ASYNC_NESTABLE_END pair. We don't want to support those old events, so we have to check we are dealing with an instant event.
|
|
113
113
|
return event.name === "DrawFrame" /* Name.DRAW_FRAME */ && event.ph === "I" /* Phase.INSTANT */;
|
|
114
114
|
}
|
|
115
|
-
export function isLegacyTraceEventDrawFrameBegin(event) {
|
|
116
|
-
return event.name === "DrawFrame" /* Name.DRAW_FRAME */ && event.ph === "b" /* Phase.ASYNC_NESTABLE_START */;
|
|
117
|
-
}
|
|
118
115
|
export function isBeginFrame(event) {
|
|
119
116
|
// Old traces did not have frameSeqId; but we do not want to support these.
|
|
120
117
|
return Boolean(event.name === "BeginFrame" /* Name.BEGIN_FRAME */ && event.args && 'frameSeqId' in event.args);
|