@paulirish/trace_engine 0.0.38 → 0.0.40

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.
Files changed (276) hide show
  1. package/.tmp/tsbuildinfo/tsconfig.tsbuildinfo +1 -1
  2. package/core/platform/DevToolsPath.d.ts +30 -9
  3. package/core/platform/DevToolsPath.js +21 -0
  4. package/core/platform/DevToolsPath.js.map +1 -1
  5. package/core/platform/MapUtilities.js +1 -1
  6. package/core/platform/MapUtilities.js.map +1 -1
  7. package/core/platform/ServerTiming.d.ts +2 -2
  8. package/core/platform/ServerTiming.js.map +1 -1
  9. package/core/platform/StringUtilities.js +1 -1
  10. package/core/platform/StringUtilities.js.map +1 -1
  11. package/core/platform/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
  12. package/core/platform/platform-tsconfig.json +2 -1
  13. package/generated/protocol.d.ts +203 -73
  14. package/locales/af.json +86 -0
  15. package/locales/am.json +86 -0
  16. package/locales/ar.json +86 -0
  17. package/locales/as.json +86 -0
  18. package/locales/az.json +86 -0
  19. package/locales/be.json +86 -0
  20. package/locales/bg.json +86 -0
  21. package/locales/bn.json +86 -0
  22. package/locales/bs.json +86 -0
  23. package/locales/ca.json +86 -0
  24. package/locales/cs.json +86 -0
  25. package/locales/cy.json +86 -0
  26. package/locales/da.json +86 -0
  27. package/locales/de.json +86 -0
  28. package/locales/el.json +86 -0
  29. package/locales/en-GB.json +86 -0
  30. package/locales/en-US.json +86 -0
  31. package/locales/en-XL.json +86 -0
  32. package/locales/es-419.json +86 -0
  33. package/locales/es.json +86 -0
  34. package/locales/et.json +86 -0
  35. package/locales/eu.json +86 -0
  36. package/locales/fa.json +86 -0
  37. package/locales/fi.json +86 -0
  38. package/locales/fil.json +86 -0
  39. package/locales/fr-CA.json +86 -0
  40. package/locales/fr.json +86 -0
  41. package/locales/gl.json +86 -0
  42. package/locales/gu.json +86 -0
  43. package/locales/he.json +86 -0
  44. package/locales/hi.json +86 -0
  45. package/locales/hr.json +86 -0
  46. package/locales/hu.json +86 -0
  47. package/locales/hy.json +86 -0
  48. package/locales/id.json +86 -0
  49. package/locales/is.json +86 -0
  50. package/locales/it.json +86 -0
  51. package/locales/ja.json +86 -0
  52. package/locales/ka.json +86 -0
  53. package/locales/kk.json +86 -0
  54. package/locales/km.json +86 -0
  55. package/locales/kn.json +86 -0
  56. package/locales/ko.json +86 -0
  57. package/locales/ky.json +86 -0
  58. package/locales/lo.json +86 -0
  59. package/locales/lt.json +86 -0
  60. package/locales/lv.json +86 -0
  61. package/locales/mk.json +86 -0
  62. package/locales/ml.json +86 -0
  63. package/locales/mn.json +86 -0
  64. package/locales/mr.json +86 -0
  65. package/locales/ms.json +86 -0
  66. package/locales/my.json +86 -0
  67. package/locales/ne.json +86 -0
  68. package/locales/nl.json +86 -0
  69. package/locales/no.json +86 -0
  70. package/locales/or.json +86 -0
  71. package/locales/pa.json +86 -0
  72. package/locales/pl.json +86 -0
  73. package/locales/pt-PT.json +86 -0
  74. package/locales/pt.json +86 -0
  75. package/locales/ro.json +86 -0
  76. package/locales/ru.json +86 -0
  77. package/locales/si.json +86 -0
  78. package/locales/sk.json +86 -0
  79. package/locales/sl.json +86 -0
  80. package/locales/sq.json +86 -0
  81. package/locales/sr-Latn.json +86 -0
  82. package/locales/sr.json +86 -0
  83. package/locales/sv.json +86 -0
  84. package/locales/sw.json +86 -0
  85. package/locales/ta.json +86 -0
  86. package/locales/te.json +86 -0
  87. package/locales/th.json +86 -0
  88. package/locales/tr.json +86 -0
  89. package/locales/uk.json +86 -0
  90. package/locales/ur.json +86 -0
  91. package/locales/uz.json +86 -0
  92. package/locales/vi.json +86 -0
  93. package/locales/zh-HK.json +86 -0
  94. package/locales/zh-TW.json +86 -0
  95. package/locales/zh.json +86 -0
  96. package/locales/zu.json +86 -0
  97. package/models/cpu_profile/ProfileTreeModel.js +0 -2
  98. package/models/cpu_profile/ProfileTreeModel.js.map +1 -1
  99. package/models/cpu_profile/cpu_profile-tsconfig.json +2 -1
  100. package/models/cpu_profile/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
  101. package/models/trace/LanternComputationData.js +1 -1
  102. package/models/trace/LanternComputationData.js.map +1 -1
  103. package/models/trace/ModelImpl.d.ts +6 -6
  104. package/models/trace/ModelImpl.js +1 -0
  105. package/models/trace/ModelImpl.js.map +1 -1
  106. package/models/trace/Processor.d.ts +6 -0
  107. package/models/trace/Processor.js +90 -9
  108. package/models/trace/Processor.js.map +1 -1
  109. package/models/trace/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
  110. package/models/trace/extras/StackTraceForEvent.d.ts +12 -0
  111. package/models/trace/extras/StackTraceForEvent.js +163 -0
  112. package/models/trace/extras/StackTraceForEvent.js.map +1 -0
  113. package/models/trace/extras/ThirdParties.d.ts +7 -4
  114. package/models/trace/extras/ThirdParties.js +56 -65
  115. package/models/trace/extras/ThirdParties.js.map +1 -1
  116. package/models/trace/extras/TraceTree.js +8 -8
  117. package/models/trace/extras/TraceTree.js.map +1 -1
  118. package/models/trace/extras/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
  119. package/models/trace/extras/extras-tsconfig.json +3 -2
  120. package/models/trace/extras/extras.js.map +1 -1
  121. package/models/trace/handlers/AnimationFramesHandler.d.ts +11 -0
  122. package/models/trace/handlers/AnimationFramesHandler.js +102 -0
  123. package/models/trace/handlers/AnimationFramesHandler.js.map +1 -0
  124. package/models/trace/handlers/AsyncJSCallsHandler.d.ts +15 -0
  125. package/models/trace/handlers/AsyncJSCallsHandler.js +153 -0
  126. package/models/trace/handlers/AsyncJSCallsHandler.js.map +1 -0
  127. package/models/trace/handlers/DOMStatsHandler.d.ts +8 -0
  128. package/models/trace/handlers/DOMStatsHandler.js +22 -0
  129. package/models/trace/handlers/DOMStatsHandler.js.map +1 -0
  130. package/models/trace/handlers/ExtensionTraceDataHandler.d.ts +80 -2
  131. package/models/trace/handlers/ExtensionTraceDataHandler.js +163 -13
  132. package/models/trace/handlers/ExtensionTraceDataHandler.js.map +1 -1
  133. package/models/trace/handlers/FlowsHandler.js +47 -55
  134. package/models/trace/handlers/FlowsHandler.js.map +1 -1
  135. package/models/trace/handlers/InitiatorsHandler.d.ts +11 -0
  136. package/models/trace/handlers/InitiatorsHandler.js +33 -25
  137. package/models/trace/handlers/InitiatorsHandler.js.map +1 -1
  138. package/models/trace/handlers/LargestImagePaintHandler.d.ts +0 -2
  139. package/models/trace/handlers/LargestImagePaintHandler.js +27 -24
  140. package/models/trace/handlers/LargestImagePaintHandler.js.map +1 -1
  141. package/models/trace/handlers/LayoutShiftsHandler.d.ts +2 -2
  142. package/models/trace/handlers/LayoutShiftsHandler.js +3 -2
  143. package/models/trace/handlers/LayoutShiftsHandler.js.map +1 -1
  144. package/models/trace/handlers/MetaHandler.d.ts +2 -2
  145. package/models/trace/handlers/MetaHandler.js +1 -1
  146. package/models/trace/handlers/MetaHandler.js.map +1 -1
  147. package/models/trace/handlers/ModelHandlers.d.ts +4 -1
  148. package/models/trace/handlers/ModelHandlers.js +4 -1
  149. package/models/trace/handlers/ModelHandlers.js.map +1 -1
  150. package/models/trace/handlers/NetworkRequestsHandler.d.ts +2 -0
  151. package/models/trace/handlers/NetworkRequestsHandler.js +21 -0
  152. package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -1
  153. package/models/trace/handlers/PageLoadMetricsHandler.d.ts +2 -2
  154. package/models/trace/handlers/PageLoadMetricsHandler.js +9 -9
  155. package/models/trace/handlers/PageLoadMetricsHandler.js.map +1 -1
  156. package/models/trace/handlers/RendererHandler.d.ts +4 -0
  157. package/models/trace/handlers/RendererHandler.js +33 -2
  158. package/models/trace/handlers/RendererHandler.js.map +1 -1
  159. package/models/trace/handlers/SamplesHandler.d.ts +2 -2
  160. package/models/trace/handlers/SamplesHandler.js +3 -3
  161. package/models/trace/handlers/SamplesHandler.js.map +1 -1
  162. package/models/trace/handlers/ServerTimingsHandler.js +2 -2
  163. package/models/trace/handlers/ServerTimingsHandler.js.map +1 -1
  164. package/models/trace/handlers/Threads.d.ts +1 -0
  165. package/models/trace/handlers/Threads.js +8 -0
  166. package/models/trace/handlers/Threads.js.map +1 -1
  167. package/models/trace/handlers/UserInteractionsHandler.js +5 -6
  168. package/models/trace/handlers/UserInteractionsHandler.js.map +1 -1
  169. package/models/trace/handlers/UserTimingsHandler.d.ts +1 -1
  170. package/models/trace/handlers/UserTimingsHandler.js +1 -1
  171. package/models/trace/handlers/UserTimingsHandler.js.map +1 -1
  172. package/models/trace/handlers/WarningsHandler.js +2 -2
  173. package/models/trace/handlers/WarningsHandler.js.map +1 -1
  174. package/models/trace/handlers/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
  175. package/models/trace/handlers/handlers-tsconfig.json +9 -1
  176. package/models/trace/handlers/handlers.d.ts +1 -0
  177. package/models/trace/handlers/handlers.js +1 -0
  178. package/models/trace/handlers/handlers.js.map +1 -1
  179. package/models/trace/handlers/helpers.d.ts +19 -0
  180. package/models/trace/handlers/helpers.js +123 -0
  181. package/models/trace/handlers/helpers.js.map +1 -0
  182. package/models/trace/helpers/SamplesIntegrator.js +2 -2
  183. package/models/trace/helpers/SamplesIntegrator.js.map +1 -1
  184. package/models/trace/helpers/SyntheticEvents.js +1 -1
  185. package/models/trace/helpers/SyntheticEvents.js.map +1 -1
  186. package/models/trace/helpers/Timing.d.ts +5 -6
  187. package/models/trace/helpers/Timing.js +22 -31
  188. package/models/trace/helpers/Timing.js.map +1 -1
  189. package/models/trace/helpers/Trace.d.ts +24 -10
  190. package/models/trace/helpers/Trace.js +53 -6
  191. package/models/trace/helpers/Trace.js.map +1 -1
  192. package/models/trace/helpers/TreeHelpers.d.ts +0 -31
  193. package/models/trace/helpers/TreeHelpers.js +1 -142
  194. package/models/trace/helpers/TreeHelpers.js.map +1 -1
  195. package/models/trace/helpers/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
  196. package/models/trace/helpers/helpers-tsconfig.json +2 -1
  197. package/models/trace/insights/CLSCulprits.js +1 -2
  198. package/models/trace/insights/CLSCulprits.js.map +1 -1
  199. package/models/trace/insights/Common.d.ts +38 -1
  200. package/models/trace/insights/Common.js +123 -0
  201. package/models/trace/insights/Common.js.map +1 -1
  202. package/models/trace/insights/DOMSize.d.ts +9 -0
  203. package/models/trace/insights/DOMSize.js +102 -0
  204. package/models/trace/insights/DOMSize.js.map +1 -0
  205. package/models/trace/insights/DocumentLatency.js +1 -1
  206. package/models/trace/insights/DocumentLatency.js.map +1 -1
  207. package/models/trace/insights/FontDisplay.js +1 -1
  208. package/models/trace/insights/FontDisplay.js.map +1 -1
  209. package/models/trace/insights/ImageDelivery.d.ts +22 -4
  210. package/models/trace/insights/ImageDelivery.js +76 -6
  211. package/models/trace/insights/ImageDelivery.js.map +1 -1
  212. package/models/trace/insights/LCPDiscovery.js +2 -2
  213. package/models/trace/insights/LCPDiscovery.js.map +1 -1
  214. package/models/trace/insights/LCPPhases.js +7 -7
  215. package/models/trace/insights/LCPPhases.js.map +1 -1
  216. package/models/trace/insights/Models.d.ts +1 -0
  217. package/models/trace/insights/Models.js +1 -0
  218. package/models/trace/insights/Models.js.map +1 -1
  219. package/models/trace/insights/Statistics.d.ts +14 -0
  220. package/models/trace/insights/Statistics.js +86 -0
  221. package/models/trace/insights/Statistics.js.map +1 -0
  222. package/models/trace/insights/ThirdParties.d.ts +2 -2
  223. package/models/trace/insights/ThirdParties.js +5 -4
  224. package/models/trace/insights/ThirdParties.js.map +1 -1
  225. package/models/trace/insights/Viewport.js +2 -2
  226. package/models/trace/insights/Viewport.js.map +1 -1
  227. package/models/trace/insights/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
  228. package/models/trace/insights/insights-tsconfig.json +4 -1
  229. package/models/trace/insights/insights.d.ts +1 -0
  230. package/models/trace/insights/insights.js +1 -0
  231. package/models/trace/insights/insights.js.map +1 -1
  232. package/models/trace/insights/types.d.ts +4 -3
  233. package/models/trace/insights/types.js.map +1 -1
  234. package/models/trace/lantern/core/NetworkAnalyzer.d.ts +2 -2
  235. package/models/trace/lantern/core/NetworkAnalyzer.js +2 -3
  236. package/models/trace/lantern/core/NetworkAnalyzer.js.map +1 -1
  237. package/models/trace/lantern/core/core-tsconfig.json +2 -1
  238. package/models/trace/lantern/core/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
  239. package/models/trace/lantern/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
  240. package/models/trace/lantern/graph/PageDependencyGraph.js +0 -1
  241. package/models/trace/lantern/graph/PageDependencyGraph.js.map +1 -1
  242. package/models/trace/lantern/graph/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
  243. package/models/trace/lantern/graph/graph-tsconfig.json +2 -1
  244. package/models/trace/lantern/lantern-tsconfig.json +2 -1
  245. package/models/trace/lantern/metrics/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
  246. package/models/trace/lantern/metrics/metrics-tsconfig.json +2 -1
  247. package/models/trace/lantern/simulation/DNSCache.d.ts +2 -2
  248. package/models/trace/lantern/simulation/DNSCache.js.map +1 -1
  249. package/models/trace/lantern/simulation/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
  250. package/models/trace/lantern/simulation/simulation-tsconfig.json +2 -1
  251. package/models/trace/lantern/types/Lantern.d.ts +10 -10
  252. package/models/trace/lantern/types/Lantern.js.map +1 -1
  253. package/models/trace/lantern/types/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
  254. package/models/trace/lantern/types/types-tsconfig.json +2 -1
  255. package/models/trace/root-causes/LayoutShift.d.ts +6 -6
  256. package/models/trace/root-causes/LayoutShift.js +1 -1
  257. package/models/trace/root-causes/LayoutShift.js.map +1 -1
  258. package/models/trace/root-causes/RootCauses.d.ts +2 -2
  259. package/models/trace/root-causes/RootCauses.js.map +1 -1
  260. package/models/trace/root-causes/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
  261. package/models/trace/root-causes/root-causes-tsconfig.json +2 -1
  262. package/models/trace/trace-tsconfig.json +2 -1
  263. package/models/trace/types/Configuration.d.ts +2 -2
  264. package/models/trace/types/Configuration.js.map +1 -1
  265. package/models/trace/types/Extensions.d.ts +3 -3
  266. package/models/trace/types/Extensions.js.map +1 -1
  267. package/models/trace/types/File.d.ts +11 -11
  268. package/models/trace/types/File.js.map +1 -1
  269. package/models/trace/types/Timing.js.map +1 -1
  270. package/models/trace/types/TraceEvents.d.ts +107 -31
  271. package/models/trace/types/TraceEvents.js +34 -14
  272. package/models/trace/types/TraceEvents.js.map +1 -1
  273. package/models/trace/types/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
  274. package/models/trace/types/types-tsconfig.json +2 -1
  275. package/package.json +1 -1
  276. package/test/test-trace-engine.mjs +8 -7
@@ -1 +1 @@
1
- {"version":3,"file":"NetworkAnalyzer.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/core/NetworkAnalyzer.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 * as Lantern from '../types/types.js';\n\nimport {LanternError} from './LanternError.js';\n\nclass UrlUtils {\n /**\n * There is fancy URL rewriting logic for the chrome://settings page that we need to work around.\n * Why? Special handling was added by Chrome team to allow a pushState transition between chrome:// pages.\n * As a result, the network URL (chrome://chrome/settings/) doesn't match the final document URL (chrome://settings/).\n */\n static rewriteChromeInternalUrl(url: string): string {\n if (!url || !url.startsWith('chrome://')) {\n return url;\n }\n // Chrome adds a trailing slash to `chrome://` URLs, but the spec does not.\n // https://github.com/GoogleChrome/lighthouse/pull/3941#discussion_r154026009\n if (url.endsWith('/')) {\n url = url.replace(/\\/$/, '');\n }\n return url.replace(/^chrome:\\/\\/chrome\\//, 'chrome://');\n }\n\n /**\n * Determine if url1 equals url2, ignoring URL fragments.\n */\n static equalWithExcludedFragments(url1: string, url2: string): boolean {\n [url1, url2] = [url1, url2].map(this.rewriteChromeInternalUrl);\n try {\n const urla = new URL(url1);\n urla.hash = '';\n\n const urlb = new URL(url2);\n urlb.hash = '';\n\n return urla.href === urlb.href;\n } catch (e) {\n return false;\n }\n }\n}\n\ninterface Summary {\n min: number;\n max: number;\n avg: number;\n median: number;\n}\n\ninterface RTTEstimateOptions {\n /**\n * TCP connection handshake information will be used when available, but in\n * some circumstances this data can be unreliable. This flag exposes an\n * option to ignore the handshake data and use the coarse download/TTFB timing data.\n */\n forceCoarseEstimates?: boolean;\n /**\n * Coarse estimates include lots of extra time and noise multiply by some factor\n * to deflate the estimates a bit.\n */\n coarseEstimateMultiplier?: number;\n /** Useful for testing to isolate the different methods of estimation. */\n useDownloadEstimates?: boolean;\n /** Useful for testing to isolate the different methods of estimation. */\n useSendStartEstimates?: boolean;\n /** Useful for testing to isolate the different methods of estimation. */\n useHeadersEndEstimates?: boolean;\n}\n\ntype RequestInfo = {\n request: Lantern.NetworkRequest,\n timing: Lantern.ResourceTiming,\n connectionReused?: boolean,\n};\n\nconst INITIAL_CWD = 14 * 1024;\n\n// Assume that 40% of TTFB was server response time by default for static assets\nconst DEFAULT_SERVER_RESPONSE_PERCENTAGE = 0.4;\n\n/**\n * For certain resource types, server response time takes up a greater percentage of TTFB (dynamic\n * assets like HTML documents, XHR/API calls, etc)\n */\nconst SERVER_RESPONSE_PERCENTAGE_OF_TTFB: Partial<Record<Lantern.ResourceType, number>> = {\n Document: 0.9,\n XHR: 0.9,\n Fetch: 0.9,\n};\n\nclass NetworkAnalyzer {\n static get summary(): string {\n return '__SUMMARY__';\n }\n\n static groupByOrigin(records: Lantern.NetworkRequest[]): Map<string, Lantern.NetworkRequest[]> {\n const grouped = new Map();\n records.forEach(item => {\n const key = item.parsedURL.securityOrigin;\n const group = grouped.get(key) || [];\n group.push(item);\n grouped.set(key, group);\n });\n return grouped;\n }\n\n static getSummary(values: number[]): Summary {\n values.sort((a, b) => a - b);\n\n let median;\n if (values.length === 0) {\n median = values[0];\n } else if (values.length % 2 === 0) {\n const a = values[Math.floor((values.length - 1) / 2)];\n const b = values[Math.floor((values.length - 1) / 2) + 1];\n median = (a + b) / 2;\n } else {\n median = values[Math.floor((values.length - 1) / 2)];\n }\n\n return {\n min: values[0],\n max: values[values.length - 1],\n avg: values.reduce((a, b) => a + b, 0) / values.length,\n median,\n };\n }\n\n static summarize(values: Map<string, number[]>): Map<string, Summary> {\n const summaryByKey = new Map();\n const allEstimates = [];\n for (const [key, estimates] of values) {\n summaryByKey.set(key, NetworkAnalyzer.getSummary(estimates));\n allEstimates.push(...estimates);\n }\n\n summaryByKey.set(NetworkAnalyzer.summary, NetworkAnalyzer.getSummary(allEstimates));\n return summaryByKey;\n }\n\n static estimateValueByOrigin(\n requests: Lantern.NetworkRequest[],\n iteratee: (e: RequestInfo) => number | number[] | undefined): Map<string, number[]> {\n const connectionWasReused = NetworkAnalyzer.estimateIfConnectionWasReused(requests);\n const groupedByOrigin = NetworkAnalyzer.groupByOrigin(requests);\n\n const estimates = new Map();\n for (const [origin, originRequests] of groupedByOrigin.entries()) {\n let originEstimates: number[] = [];\n\n for (const request of originRequests) {\n const timing = request.timing;\n if (!timing) {\n continue;\n }\n\n const value = iteratee({\n request,\n timing,\n connectionReused: connectionWasReused.get(request.requestId),\n });\n if (typeof value !== 'undefined') {\n originEstimates = originEstimates.concat(value);\n }\n }\n\n if (!originEstimates.length) {\n continue;\n }\n estimates.set(origin, originEstimates);\n }\n\n return estimates;\n }\n\n /**\n * Estimates the observed RTT to each origin based on how long the connection setup.\n * For h1 and h2, this could includes two estimates - one for the TCP handshake, another for\n * SSL negotiation.\n * For h3, we get only one estimate since QUIC establishes a secure connection in a\n * single handshake.\n * This is the most accurate and preferred method of measurement when the data is available.\n */\n static estimateRTTViaConnectionTiming(info: RequestInfo): number[]|number|undefined {\n const {timing, connectionReused, request} = info;\n if (connectionReused) {\n return;\n }\n\n const {connectStart, sslStart, sslEnd, connectEnd} = timing;\n if (connectEnd >= 0 && connectStart >= 0 && request.protocol.startsWith('h3')) {\n // These values are equal to sslStart and sslEnd for h3.\n return connectEnd - connectStart;\n }\n if (sslStart >= 0 && sslEnd >= 0 && sslStart !== connectStart) {\n // SSL can also be more than 1 RT but assume False Start was used.\n return [connectEnd - sslStart, sslStart - connectStart];\n }\n if (connectStart >= 0 && connectEnd >= 0) {\n return connectEnd - connectStart;\n }\n\n return;\n }\n\n /**\n * Estimates the observed RTT to each origin based on how long a download took on a fresh connection.\n * NOTE: this will tend to overestimate the actual RTT quite significantly as the download can be\n * slow for other reasons as well such as bandwidth constraints.\n */\n static estimateRTTViaDownloadTiming(info: RequestInfo): number|undefined {\n const {timing, connectionReused, request} = info;\n if (connectionReused) {\n return;\n }\n\n // Only look at downloads that went past the initial congestion window\n if (request.transferSize <= INITIAL_CWD) {\n return;\n }\n if (!Number.isFinite(timing.receiveHeadersEnd) || timing.receiveHeadersEnd < 0) {\n return;\n }\n\n // Compute the amount of time downloading everything after the first congestion window took\n const totalTime = request.networkEndTime - request.networkRequestTime;\n const downloadTimeAfterFirstByte = totalTime - timing.receiveHeadersEnd;\n const numberOfRoundTrips = Math.log2(request.transferSize / INITIAL_CWD);\n\n // Ignore requests that required a high number of round trips since bandwidth starts to play\n // a larger role than latency\n if (numberOfRoundTrips > 5) {\n return;\n }\n\n return downloadTimeAfterFirstByte / numberOfRoundTrips;\n }\n\n /**\n * Estimates the observed RTT to each origin based on how long it took until Chrome could\n * start sending the actual request when a new connection was required.\n * NOTE: this will tend to overestimate the actual RTT as the request can be delayed for other\n * reasons as well such as more SSL handshakes if TLS False Start is not enabled.\n */\n static estimateRTTViaSendStartTiming(info: RequestInfo): number|undefined {\n const {timing, connectionReused, request} = info;\n if (connectionReused) {\n return;\n }\n\n if (!Number.isFinite(timing.sendStart) || timing.sendStart < 0) {\n return;\n }\n\n // Assume everything before sendStart was just DNS + (SSL)? + TCP handshake\n // 1 RT for DNS, 1 RT (maybe) for SSL, 1 RT for TCP\n let roundTrips = 1;\n // TCP\n if (!request.protocol.startsWith('h3')) {\n roundTrips += 1;\n }\n if (request.parsedURL.scheme === 'https') {\n roundTrips += 1;\n }\n return timing.sendStart / roundTrips;\n }\n\n /**\n * Estimates the observed RTT to each origin based on how long it took until Chrome received the\n * headers of the response (~TTFB).\n * NOTE: this is the most inaccurate way to estimate the RTT, but in some environments it's all\n * we have access to :(\n */\n static estimateRTTViaHeadersEndTiming(info: RequestInfo): number|undefined {\n const {timing, connectionReused, request} = info;\n if (!Number.isFinite(timing.receiveHeadersEnd) || timing.receiveHeadersEnd < 0) {\n return;\n }\n if (!request.resourceType) {\n return;\n }\n\n const serverResponseTimePercentage =\n SERVER_RESPONSE_PERCENTAGE_OF_TTFB[request.resourceType] || DEFAULT_SERVER_RESPONSE_PERCENTAGE;\n const estimatedServerResponseTime = timing.receiveHeadersEnd * serverResponseTimePercentage;\n\n // When connection was reused...\n // TTFB = 1 RT for request + server response time\n let roundTrips = 1;\n\n // When connection was fresh...\n // TTFB = DNS + (SSL)? + TCP handshake + 1 RT for request + server response time\n if (!connectionReused) {\n roundTrips += 1; // DNS\n if (!request.protocol.startsWith('h3')) {\n roundTrips += 1; // TCP\n }\n if (request.parsedURL.scheme === 'https') {\n roundTrips += 1; // SSL\n }\n }\n\n // subtract out our estimated server response time\n return Math.max((timing.receiveHeadersEnd - estimatedServerResponseTime) / roundTrips, 3);\n }\n\n /**\n * Given the RTT to each origin, estimates the observed server response times.\n */\n static estimateResponseTimeByOrigin(records: Lantern.NetworkRequest[], rttByOrigin: Map<string, number>):\n Map<string, number[]> {\n return NetworkAnalyzer.estimateValueByOrigin(records, ({request, timing}) => {\n if (request.serverResponseTime !== undefined) {\n return request.serverResponseTime;\n }\n\n if (!Number.isFinite(timing.receiveHeadersEnd) || timing.receiveHeadersEnd < 0) {\n return;\n }\n if (!Number.isFinite(timing.sendEnd) || timing.sendEnd < 0) {\n return;\n }\n\n const ttfb = timing.receiveHeadersEnd - timing.sendEnd;\n const origin = request.parsedURL.securityOrigin;\n const rtt = rttByOrigin.get(origin) || rttByOrigin.get(NetworkAnalyzer.summary) || 0;\n return Math.max(ttfb - rtt, 0);\n });\n }\n\n static canTrustConnectionInformation(requests: Lantern.NetworkRequest[]): boolean {\n const connectionIdWasStarted = new Map();\n for (const request of requests) {\n const started = connectionIdWasStarted.get(request.connectionId) || !request.connectionReused;\n connectionIdWasStarted.set(request.connectionId, started);\n }\n\n // We probably can't trust the network information if all the connection IDs were the same\n if (connectionIdWasStarted.size <= 1) {\n return false;\n }\n // Or if there were connections that were always reused (a connection had to have started at some point)\n return Array.from(connectionIdWasStarted.values()).every(started => started);\n }\n\n /**\n * Returns a map of requestId -> connectionReused, estimating the information if the information\n * available in the records themselves appears untrustworthy.\n */\n static estimateIfConnectionWasReused(records: Lantern.NetworkRequest[], options?: {forceCoarseEstimates: boolean}):\n Map<string, boolean> {\n const {forceCoarseEstimates = false} = options || {};\n\n // Check if we can trust the connection information coming from the protocol\n if (!forceCoarseEstimates && NetworkAnalyzer.canTrustConnectionInformation(records)) {\n return new Map(records.map(request => [request.requestId, Boolean(request.connectionReused)]));\n }\n\n // Otherwise we're on our own, a request may not have needed a fresh connection if...\n // - It was not the first request to the domain\n // - It was H2\n // - It was after the first request to the domain ended\n const connectionWasReused = new Map();\n const groupedByOrigin = NetworkAnalyzer.groupByOrigin(records);\n for (const originRecords of groupedByOrigin.values()) {\n const earliestReusePossible =\n originRecords.map(request => request.networkEndTime).reduce((a, b) => Math.min(a, b), Infinity);\n\n for (const request of originRecords) {\n connectionWasReused.set(\n request.requestId,\n request.networkRequestTime >= earliestReusePossible || request.protocol === 'h2',\n );\n }\n\n const firstRecord = originRecords.reduce((a, b) => {\n return a.networkRequestTime > b.networkRequestTime ? b : a;\n });\n connectionWasReused.set(firstRecord.requestId, false);\n }\n\n return connectionWasReused;\n }\n\n /**\n * Estimates the RTT to each origin by examining observed network timing information.\n * Attempts to use the most accurate information first and falls back to coarser estimates when it\n * is unavailable.\n */\n static estimateRTTByOrigin(records: Lantern.NetworkRequest[], options?: RTTEstimateOptions): Map<string, Summary> {\n const {\n forceCoarseEstimates = false,\n // coarse estimates include lots of extra time and noise\n // multiply by some factor to deflate the estimates a bit.\n coarseEstimateMultiplier = 0.3,\n useDownloadEstimates = true,\n useSendStartEstimates = true,\n useHeadersEndEstimates = true,\n } = options || {};\n\n const connectionWasReused = NetworkAnalyzer.estimateIfConnectionWasReused(records);\n const groupedByOrigin = NetworkAnalyzer.groupByOrigin(records);\n\n const estimatesByOrigin = new Map();\n for (const [origin, originRequests] of groupedByOrigin.entries()) {\n const originEstimates: number[] = [];\n\n // eslint-disable-next-line no-inner-declarations\n function collectEstimates(estimator: (e: RequestInfo) => number[] | number | undefined, multiplier = 1): void {\n for (const request of originRequests) {\n const timing = request.timing;\n if (!timing || !request.transferSize) {\n continue;\n }\n\n const estimates = estimator({\n request,\n timing,\n connectionReused: connectionWasReused.get(request.requestId),\n });\n if (estimates === undefined) {\n continue;\n }\n\n if (!Array.isArray(estimates)) {\n originEstimates.push(estimates * multiplier);\n } else {\n originEstimates.push(...estimates.map(e => e * multiplier));\n }\n }\n }\n\n if (!forceCoarseEstimates) {\n collectEstimates(this.estimateRTTViaConnectionTiming);\n }\n\n // Connection timing can be missing for a few reasons:\n // - Origin was preconnected, which we don't have instrumentation for.\n // - Trace began recording after a connection has already been established (for example, in timespan mode)\n // - Perhaps Chrome established a connection already in the background (service worker? Just guessing here)\n // - Not provided in LR netstack.\n if (!originEstimates.length) {\n if (useDownloadEstimates) {\n collectEstimates(this.estimateRTTViaDownloadTiming, coarseEstimateMultiplier);\n }\n if (useSendStartEstimates) {\n collectEstimates(this.estimateRTTViaSendStartTiming, coarseEstimateMultiplier);\n }\n if (useHeadersEndEstimates) {\n collectEstimates(this.estimateRTTViaHeadersEndTiming, coarseEstimateMultiplier);\n }\n }\n\n if (originEstimates.length) {\n estimatesByOrigin.set(origin, originEstimates);\n }\n }\n\n if (!estimatesByOrigin.size) {\n throw new LanternError('No timing information available');\n }\n return NetworkAnalyzer.summarize(estimatesByOrigin);\n }\n\n /**\n * Estimates the server response time of each origin. RTT times can be passed in or will be\n * estimated automatically if not provided.\n */\n static estimateServerResponseTimeByOrigin(records: Lantern.NetworkRequest[], options?: RTTEstimateOptions&{\n rttByOrigin?: Map<string, number>,\n }): Map<string, Summary> {\n let rttByOrigin = (options || {}).rttByOrigin;\n if (!rttByOrigin) {\n rttByOrigin = new Map();\n\n const rttSummaryByOrigin = NetworkAnalyzer.estimateRTTByOrigin(records, options);\n for (const [origin, summary] of rttSummaryByOrigin.entries()) {\n rttByOrigin.set(origin, summary.min);\n }\n }\n\n const estimatesByOrigin = NetworkAnalyzer.estimateResponseTimeByOrigin(records, rttByOrigin);\n return NetworkAnalyzer.summarize(estimatesByOrigin);\n }\n\n /**\n * Computes the average throughput for the given requests in bits/second.\n * Excludes data URI, failed or otherwise incomplete, and cached requests.\n * Returns null if there were no analyzable network requests.\n */\n static estimateThroughput(records: Lantern.NetworkRequest[]): number|null {\n let totalBytes = 0;\n\n // We will measure throughput by summing the total bytes downloaded by the total time spent\n // downloading those bytes. We slice up all the network requests into start/end boundaries, so\n // it's easier to deal with the gaps in downloading.\n const timeBoundaries = records\n .reduce(\n (boundaries, request) => {\n const scheme = request.parsedURL?.scheme;\n // Requests whose bodies didn't come over the network or didn't completely finish will mess\n // with the computation, just skip over them.\n if (scheme === 'data' || request.failed || !request.finished ||\n request.statusCode > 300 || !request.transferSize) {\n return boundaries;\n }\n\n // If we've made it this far, all the times we need should be valid (i.e. not undefined/-1).\n totalBytes += request.transferSize;\n boundaries.push({time: request.responseHeadersEndTime / 1000, isStart: true});\n boundaries.push({time: request.networkEndTime / 1000, isStart: false});\n return boundaries;\n },\n [] as Array<{time: number, isStart: boolean}>)\n .sort((a, b) => a.time - b.time);\n\n if (!timeBoundaries.length) {\n return null;\n }\n\n let inflight = 0;\n let currentStart = 0;\n let totalDuration = 0;\n\n timeBoundaries.forEach(boundary => {\n if (boundary.isStart) {\n if (inflight === 0) {\n // We just ended a quiet period, keep track of when the download period started\n currentStart = boundary.time;\n }\n inflight++;\n } else {\n inflight--;\n if (inflight === 0) {\n // We just entered a quiet period, update our duration with the time we spent downloading\n totalDuration += boundary.time - currentStart;\n }\n }\n });\n\n return totalBytes * 8 / totalDuration;\n }\n\n static computeRTTAndServerResponseTime(records: Lantern.NetworkRequest[]):\n {rtt: number, additionalRttByOrigin: Map<string, number>, serverResponseTimeByOrigin: Map<string, number>} {\n // First pass compute the estimated observed RTT to each origin's servers.\n const rttByOrigin = new Map<string, number>();\n for (const [origin, summary] of NetworkAnalyzer.estimateRTTByOrigin(records).entries()) {\n rttByOrigin.set(origin, summary.min);\n }\n\n // We'll use the minimum RTT as the assumed connection latency since we care about how much addt'l\n // latency each origin introduces as Lantern will be simulating with its own connection latency.\n const minimumRtt = Math.min(...Array.from(rttByOrigin.values()));\n // We'll use the observed RTT information to help estimate the server response time\n const responseTimeSummaries = NetworkAnalyzer.estimateServerResponseTimeByOrigin(records, {\n rttByOrigin,\n });\n\n const additionalRttByOrigin = new Map<string, number>();\n const serverResponseTimeByOrigin = new Map<string, number>();\n for (const [origin, summary] of responseTimeSummaries.entries()) {\n // Not all origins have usable timing data, we'll default to using no additional latency.\n const rttForOrigin = rttByOrigin.get(origin) || minimumRtt;\n additionalRttByOrigin.set(origin, rttForOrigin - minimumRtt);\n serverResponseTimeByOrigin.set(origin, summary.median);\n }\n\n return {\n rtt: minimumRtt,\n additionalRttByOrigin,\n serverResponseTimeByOrigin,\n };\n }\n\n static analyze(records: Lantern.NetworkRequest[]): Lantern.Simulation.Settings['networkAnalysis']|null {\n const throughput = NetworkAnalyzer.estimateThroughput(records);\n if (throughput === null) {\n return null;\n }\n\n return {\n throughput,\n ...NetworkAnalyzer.computeRTTAndServerResponseTime(records),\n };\n }\n\n static findResourceForUrl<T extends Lantern.NetworkRequest>(records: Array<T>, resourceUrl: string): T|undefined {\n // equalWithExcludedFragments is expensive, so check that the resourceUrl starts with the request url first\n return records.find(\n request => resourceUrl.startsWith(request.url) && UrlUtils.equalWithExcludedFragments(request.url, resourceUrl),\n );\n }\n\n static findLastDocumentForUrl<T extends Lantern.NetworkRequest>(records: Array<T>, resourceUrl: string): T|undefined {\n // equalWithExcludedFragments is expensive, so check that the resourceUrl starts with the request url first\n const matchingRequests = records.filter(\n request => request.resourceType === 'Document' &&\n // Note: `request.url` should never have a fragment, else this optimization gives wrong results.\n resourceUrl.startsWith(request.url) && UrlUtils.equalWithExcludedFragments(request.url, resourceUrl),\n );\n return matchingRequests[matchingRequests.length - 1];\n }\n\n /**\n * Resolves redirect chain given a main document.\n * See: {@link NetworkAnalyzer.findLastDocumentForUrl} for how to retrieve main document.\n */\n static resolveRedirects<T extends Lantern.NetworkRequest>(request: T): T {\n while (request.redirectDestination) {\n request = request.redirectDestination as T;\n }\n return request;\n }\n}\n\nexport {NetworkAnalyzer};\n"]}
1
+ {"version":3,"file":"NetworkAnalyzer.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/core/NetworkAnalyzer.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 * as Lantern from '../types/types.js';\n\nimport {LanternError} from './LanternError.js';\n\nclass UrlUtils {\n /**\n * There is fancy URL rewriting logic for the chrome://settings page that we need to work around.\n * Why? Special handling was added by Chrome team to allow a pushState transition between chrome:// pages.\n * As a result, the network URL (chrome://chrome/settings/) doesn't match the final document URL (chrome://settings/).\n */\n static rewriteChromeInternalUrl(url: string): string {\n if (!url || !url.startsWith('chrome://')) {\n return url;\n }\n // Chrome adds a trailing slash to `chrome://` URLs, but the spec does not.\n // https://github.com/GoogleChrome/lighthouse/pull/3941#discussion_r154026009\n if (url.endsWith('/')) {\n url = url.replace(/\\/$/, '');\n }\n return url.replace(/^chrome:\\/\\/chrome\\//, 'chrome://');\n }\n\n /**\n * Determine if url1 equals url2, ignoring URL fragments.\n */\n static equalWithExcludedFragments(url1: string, url2: string): boolean {\n [url1, url2] = [url1, url2].map(this.rewriteChromeInternalUrl);\n try {\n const urla = new URL(url1);\n urla.hash = '';\n\n const urlb = new URL(url2);\n urlb.hash = '';\n\n return urla.href === urlb.href;\n } catch {\n return false;\n }\n }\n}\n\ninterface Summary {\n min: number;\n max: number;\n avg: number;\n median: number;\n}\n\ninterface RTTEstimateOptions {\n /**\n * TCP connection handshake information will be used when available, but in\n * some circumstances this data can be unreliable. This flag exposes an\n * option to ignore the handshake data and use the coarse download/TTFB timing data.\n */\n forceCoarseEstimates?: boolean;\n /**\n * Coarse estimates include lots of extra time and noise multiply by some factor\n * to deflate the estimates a bit.\n */\n coarseEstimateMultiplier?: number;\n /** Useful for testing to isolate the different methods of estimation. */\n useDownloadEstimates?: boolean;\n /** Useful for testing to isolate the different methods of estimation. */\n useSendStartEstimates?: boolean;\n /** Useful for testing to isolate the different methods of estimation. */\n useHeadersEndEstimates?: boolean;\n}\n\ninterface RequestInfo {\n request: Lantern.NetworkRequest;\n timing: Lantern.ResourceTiming;\n connectionReused?: boolean;\n}\n\nconst INITIAL_CWD = 14 * 1024;\n\n// Assume that 40% of TTFB was server response time by default for static assets\nconst DEFAULT_SERVER_RESPONSE_PERCENTAGE = 0.4;\n\n/**\n * For certain resource types, server response time takes up a greater percentage of TTFB (dynamic\n * assets like HTML documents, XHR/API calls, etc)\n */\nconst SERVER_RESPONSE_PERCENTAGE_OF_TTFB: Partial<Record<Lantern.ResourceType, number>> = {\n Document: 0.9,\n XHR: 0.9,\n Fetch: 0.9,\n};\n\nclass NetworkAnalyzer {\n static get summary(): string {\n return '__SUMMARY__';\n }\n\n static groupByOrigin(records: Lantern.NetworkRequest[]): Map<string, Lantern.NetworkRequest[]> {\n const grouped = new Map();\n records.forEach(item => {\n const key = item.parsedURL.securityOrigin;\n const group = grouped.get(key) || [];\n group.push(item);\n grouped.set(key, group);\n });\n return grouped;\n }\n\n static getSummary(values: number[]): Summary {\n values.sort((a, b) => a - b);\n\n let median;\n if (values.length === 0) {\n median = values[0];\n } else if (values.length % 2 === 0) {\n const a = values[Math.floor((values.length - 1) / 2)];\n const b = values[Math.floor((values.length - 1) / 2) + 1];\n median = (a + b) / 2;\n } else {\n median = values[Math.floor((values.length - 1) / 2)];\n }\n\n return {\n min: values[0],\n max: values[values.length - 1],\n avg: values.reduce((a, b) => a + b, 0) / values.length,\n median,\n };\n }\n\n static summarize(values: Map<string, number[]>): Map<string, Summary> {\n const summaryByKey = new Map();\n const allEstimates = [];\n for (const [key, estimates] of values) {\n summaryByKey.set(key, NetworkAnalyzer.getSummary(estimates));\n allEstimates.push(...estimates);\n }\n\n summaryByKey.set(NetworkAnalyzer.summary, NetworkAnalyzer.getSummary(allEstimates));\n return summaryByKey;\n }\n\n static estimateValueByOrigin(\n requests: Lantern.NetworkRequest[],\n iteratee: (e: RequestInfo) => number | number[] | undefined): Map<string, number[]> {\n const connectionWasReused = NetworkAnalyzer.estimateIfConnectionWasReused(requests);\n const groupedByOrigin = NetworkAnalyzer.groupByOrigin(requests);\n\n const estimates = new Map();\n for (const [origin, originRequests] of groupedByOrigin.entries()) {\n let originEstimates: number[] = [];\n\n for (const request of originRequests) {\n const timing = request.timing;\n if (!timing) {\n continue;\n }\n\n const value = iteratee({\n request,\n timing,\n connectionReused: connectionWasReused.get(request.requestId),\n });\n if (typeof value !== 'undefined') {\n originEstimates = originEstimates.concat(value);\n }\n }\n\n if (!originEstimates.length) {\n continue;\n }\n estimates.set(origin, originEstimates);\n }\n\n return estimates;\n }\n\n /**\n * Estimates the observed RTT to each origin based on how long the connection setup.\n * For h1 and h2, this could includes two estimates - one for the TCP handshake, another for\n * SSL negotiation.\n * For h3, we get only one estimate since QUIC establishes a secure connection in a\n * single handshake.\n * This is the most accurate and preferred method of measurement when the data is available.\n */\n static estimateRTTViaConnectionTiming(info: RequestInfo): number[]|number|undefined {\n const {timing, connectionReused, request} = info;\n if (connectionReused) {\n return;\n }\n\n const {connectStart, sslStart, sslEnd, connectEnd} = timing;\n if (connectEnd >= 0 && connectStart >= 0 && request.protocol.startsWith('h3')) {\n // These values are equal to sslStart and sslEnd for h3.\n return connectEnd - connectStart;\n }\n if (sslStart >= 0 && sslEnd >= 0 && sslStart !== connectStart) {\n // SSL can also be more than 1 RT but assume False Start was used.\n return [connectEnd - sslStart, sslStart - connectStart];\n }\n if (connectStart >= 0 && connectEnd >= 0) {\n return connectEnd - connectStart;\n }\n\n return;\n }\n\n /**\n * Estimates the observed RTT to each origin based on how long a download took on a fresh connection.\n * NOTE: this will tend to overestimate the actual RTT quite significantly as the download can be\n * slow for other reasons as well such as bandwidth constraints.\n */\n static estimateRTTViaDownloadTiming(info: RequestInfo): number|undefined {\n const {timing, connectionReused, request} = info;\n if (connectionReused) {\n return;\n }\n\n // Only look at downloads that went past the initial congestion window\n if (request.transferSize <= INITIAL_CWD) {\n return;\n }\n if (!Number.isFinite(timing.receiveHeadersEnd) || timing.receiveHeadersEnd < 0) {\n return;\n }\n\n // Compute the amount of time downloading everything after the first congestion window took\n const totalTime = request.networkEndTime - request.networkRequestTime;\n const downloadTimeAfterFirstByte = totalTime - timing.receiveHeadersEnd;\n const numberOfRoundTrips = Math.log2(request.transferSize / INITIAL_CWD);\n\n // Ignore requests that required a high number of round trips since bandwidth starts to play\n // a larger role than latency\n if (numberOfRoundTrips > 5) {\n return;\n }\n\n return downloadTimeAfterFirstByte / numberOfRoundTrips;\n }\n\n /**\n * Estimates the observed RTT to each origin based on how long it took until Chrome could\n * start sending the actual request when a new connection was required.\n * NOTE: this will tend to overestimate the actual RTT as the request can be delayed for other\n * reasons as well such as more SSL handshakes if TLS False Start is not enabled.\n */\n static estimateRTTViaSendStartTiming(info: RequestInfo): number|undefined {\n const {timing, connectionReused, request} = info;\n if (connectionReused) {\n return;\n }\n\n if (!Number.isFinite(timing.sendStart) || timing.sendStart < 0) {\n return;\n }\n\n // Assume everything before sendStart was just DNS + (SSL)? + TCP handshake\n // 1 RT for DNS, 1 RT (maybe) for SSL, 1 RT for TCP\n let roundTrips = 1;\n // TCP\n if (!request.protocol.startsWith('h3')) {\n roundTrips += 1;\n }\n if (request.parsedURL.scheme === 'https') {\n roundTrips += 1;\n }\n return timing.sendStart / roundTrips;\n }\n\n /**\n * Estimates the observed RTT to each origin based on how long it took until Chrome received the\n * headers of the response (~TTFB).\n * NOTE: this is the most inaccurate way to estimate the RTT, but in some environments it's all\n * we have access to :(\n */\n static estimateRTTViaHeadersEndTiming(info: RequestInfo): number|undefined {\n const {timing, connectionReused, request} = info;\n if (!Number.isFinite(timing.receiveHeadersEnd) || timing.receiveHeadersEnd < 0) {\n return;\n }\n if (!request.resourceType) {\n return;\n }\n\n const serverResponseTimePercentage =\n SERVER_RESPONSE_PERCENTAGE_OF_TTFB[request.resourceType] || DEFAULT_SERVER_RESPONSE_PERCENTAGE;\n const estimatedServerResponseTime = timing.receiveHeadersEnd * serverResponseTimePercentage;\n\n // When connection was reused...\n // TTFB = 1 RT for request + server response time\n let roundTrips = 1;\n\n // When connection was fresh...\n // TTFB = DNS + (SSL)? + TCP handshake + 1 RT for request + server response time\n if (!connectionReused) {\n roundTrips += 1; // DNS\n if (!request.protocol.startsWith('h3')) {\n roundTrips += 1; // TCP\n }\n if (request.parsedURL.scheme === 'https') {\n roundTrips += 1; // SSL\n }\n }\n\n // subtract out our estimated server response time\n return Math.max((timing.receiveHeadersEnd - estimatedServerResponseTime) / roundTrips, 3);\n }\n\n /**\n * Given the RTT to each origin, estimates the observed server response times.\n */\n static estimateResponseTimeByOrigin(records: Lantern.NetworkRequest[], rttByOrigin: Map<string, number>):\n Map<string, number[]> {\n return NetworkAnalyzer.estimateValueByOrigin(records, ({request, timing}) => {\n if (request.serverResponseTime !== undefined) {\n return request.serverResponseTime;\n }\n\n if (!Number.isFinite(timing.receiveHeadersEnd) || timing.receiveHeadersEnd < 0) {\n return;\n }\n if (!Number.isFinite(timing.sendEnd) || timing.sendEnd < 0) {\n return;\n }\n\n const ttfb = timing.receiveHeadersEnd - timing.sendEnd;\n const origin = request.parsedURL.securityOrigin;\n const rtt = rttByOrigin.get(origin) || rttByOrigin.get(NetworkAnalyzer.summary) || 0;\n return Math.max(ttfb - rtt, 0);\n });\n }\n\n static canTrustConnectionInformation(requests: Lantern.NetworkRequest[]): boolean {\n const connectionIdWasStarted = new Map();\n for (const request of requests) {\n const started = connectionIdWasStarted.get(request.connectionId) || !request.connectionReused;\n connectionIdWasStarted.set(request.connectionId, started);\n }\n\n // We probably can't trust the network information if all the connection IDs were the same\n if (connectionIdWasStarted.size <= 1) {\n return false;\n }\n // Or if there were connections that were always reused (a connection had to have started at some point)\n return Array.from(connectionIdWasStarted.values()).every(started => started);\n }\n\n /**\n * Returns a map of requestId -> connectionReused, estimating the information if the information\n * available in the records themselves appears untrustworthy.\n */\n static estimateIfConnectionWasReused(records: Lantern.NetworkRequest[], options?: {forceCoarseEstimates: boolean}):\n Map<string, boolean> {\n const {forceCoarseEstimates = false} = options || {};\n\n // Check if we can trust the connection information coming from the protocol\n if (!forceCoarseEstimates && NetworkAnalyzer.canTrustConnectionInformation(records)) {\n return new Map(records.map(request => [request.requestId, Boolean(request.connectionReused)]));\n }\n\n // Otherwise we're on our own, a request may not have needed a fresh connection if...\n // - It was not the first request to the domain\n // - It was H2\n // - It was after the first request to the domain ended\n const connectionWasReused = new Map();\n const groupedByOrigin = NetworkAnalyzer.groupByOrigin(records);\n for (const originRecords of groupedByOrigin.values()) {\n const earliestReusePossible =\n originRecords.map(request => request.networkEndTime).reduce((a, b) => Math.min(a, b), Infinity);\n\n for (const request of originRecords) {\n connectionWasReused.set(\n request.requestId,\n request.networkRequestTime >= earliestReusePossible || request.protocol === 'h2',\n );\n }\n\n const firstRecord = originRecords.reduce((a, b) => {\n return a.networkRequestTime > b.networkRequestTime ? b : a;\n });\n connectionWasReused.set(firstRecord.requestId, false);\n }\n\n return connectionWasReused;\n }\n\n /**\n * Estimates the RTT to each origin by examining observed network timing information.\n * Attempts to use the most accurate information first and falls back to coarser estimates when it\n * is unavailable.\n */\n static estimateRTTByOrigin(records: Lantern.NetworkRequest[], options?: RTTEstimateOptions): Map<string, Summary> {\n const {\n forceCoarseEstimates = false,\n // coarse estimates include lots of extra time and noise\n // multiply by some factor to deflate the estimates a bit.\n coarseEstimateMultiplier = 0.3,\n useDownloadEstimates = true,\n useSendStartEstimates = true,\n useHeadersEndEstimates = true,\n } = options || {};\n\n const connectionWasReused = NetworkAnalyzer.estimateIfConnectionWasReused(records);\n const groupedByOrigin = NetworkAnalyzer.groupByOrigin(records);\n\n const estimatesByOrigin = new Map();\n for (const [origin, originRequests] of groupedByOrigin.entries()) {\n const originEstimates: number[] = [];\n\n function collectEstimates(estimator: (e: RequestInfo) => number[] | number | undefined, multiplier = 1): void {\n for (const request of originRequests) {\n const timing = request.timing;\n if (!timing || !request.transferSize) {\n continue;\n }\n\n const estimates = estimator({\n request,\n timing,\n connectionReused: connectionWasReused.get(request.requestId),\n });\n if (estimates === undefined) {\n continue;\n }\n\n if (!Array.isArray(estimates)) {\n originEstimates.push(estimates * multiplier);\n } else {\n originEstimates.push(...estimates.map(e => e * multiplier));\n }\n }\n }\n\n if (!forceCoarseEstimates) {\n collectEstimates(this.estimateRTTViaConnectionTiming);\n }\n\n // Connection timing can be missing for a few reasons:\n // - Origin was preconnected, which we don't have instrumentation for.\n // - Trace began recording after a connection has already been established (for example, in timespan mode)\n // - Perhaps Chrome established a connection already in the background (service worker? Just guessing here)\n // - Not provided in LR netstack.\n if (!originEstimates.length) {\n if (useDownloadEstimates) {\n collectEstimates(this.estimateRTTViaDownloadTiming, coarseEstimateMultiplier);\n }\n if (useSendStartEstimates) {\n collectEstimates(this.estimateRTTViaSendStartTiming, coarseEstimateMultiplier);\n }\n if (useHeadersEndEstimates) {\n collectEstimates(this.estimateRTTViaHeadersEndTiming, coarseEstimateMultiplier);\n }\n }\n\n if (originEstimates.length) {\n estimatesByOrigin.set(origin, originEstimates);\n }\n }\n\n if (!estimatesByOrigin.size) {\n throw new LanternError('No timing information available');\n }\n return NetworkAnalyzer.summarize(estimatesByOrigin);\n }\n\n /**\n * Estimates the server response time of each origin. RTT times can be passed in or will be\n * estimated automatically if not provided.\n */\n static estimateServerResponseTimeByOrigin(records: Lantern.NetworkRequest[], options?: RTTEstimateOptions&{\n rttByOrigin?: Map<string, number>,\n }): Map<string, Summary> {\n let rttByOrigin = (options || {}).rttByOrigin;\n if (!rttByOrigin) {\n rttByOrigin = new Map();\n\n const rttSummaryByOrigin = NetworkAnalyzer.estimateRTTByOrigin(records, options);\n for (const [origin, summary] of rttSummaryByOrigin.entries()) {\n rttByOrigin.set(origin, summary.min);\n }\n }\n\n const estimatesByOrigin = NetworkAnalyzer.estimateResponseTimeByOrigin(records, rttByOrigin);\n return NetworkAnalyzer.summarize(estimatesByOrigin);\n }\n\n /**\n * Computes the average throughput for the given requests in bits/second.\n * Excludes data URI, failed or otherwise incomplete, and cached requests.\n * Returns null if there were no analyzable network requests.\n */\n static estimateThroughput(records: Lantern.NetworkRequest[]): number|null {\n let totalBytes = 0;\n\n // We will measure throughput by summing the total bytes downloaded by the total time spent\n // downloading those bytes. We slice up all the network requests into start/end boundaries, so\n // it's easier to deal with the gaps in downloading.\n const timeBoundaries = records\n .reduce(\n (boundaries, request) => {\n const scheme = request.parsedURL?.scheme;\n // Requests whose bodies didn't come over the network or didn't completely finish will mess\n // with the computation, just skip over them.\n if (scheme === 'data' || request.failed || !request.finished ||\n request.statusCode > 300 || !request.transferSize) {\n return boundaries;\n }\n\n // If we've made it this far, all the times we need should be valid (i.e. not undefined/-1).\n totalBytes += request.transferSize;\n boundaries.push({time: request.responseHeadersEndTime / 1000, isStart: true});\n boundaries.push({time: request.networkEndTime / 1000, isStart: false});\n return boundaries;\n },\n [] as Array<{time: number, isStart: boolean}>)\n .sort((a, b) => a.time - b.time);\n\n if (!timeBoundaries.length) {\n return null;\n }\n\n let inflight = 0;\n let currentStart = 0;\n let totalDuration = 0;\n\n timeBoundaries.forEach(boundary => {\n if (boundary.isStart) {\n if (inflight === 0) {\n // We just ended a quiet period, keep track of when the download period started\n currentStart = boundary.time;\n }\n inflight++;\n } else {\n inflight--;\n if (inflight === 0) {\n // We just entered a quiet period, update our duration with the time we spent downloading\n totalDuration += boundary.time - currentStart;\n }\n }\n });\n\n return totalBytes * 8 / totalDuration;\n }\n\n static computeRTTAndServerResponseTime(records: Lantern.NetworkRequest[]):\n {rtt: number, additionalRttByOrigin: Map<string, number>, serverResponseTimeByOrigin: Map<string, number>} {\n // First pass compute the estimated observed RTT to each origin's servers.\n const rttByOrigin = new Map<string, number>();\n for (const [origin, summary] of NetworkAnalyzer.estimateRTTByOrigin(records).entries()) {\n rttByOrigin.set(origin, summary.min);\n }\n\n // We'll use the minimum RTT as the assumed connection latency since we care about how much addt'l\n // latency each origin introduces as Lantern will be simulating with its own connection latency.\n const minimumRtt = Math.min(...Array.from(rttByOrigin.values()));\n // We'll use the observed RTT information to help estimate the server response time\n const responseTimeSummaries = NetworkAnalyzer.estimateServerResponseTimeByOrigin(records, {\n rttByOrigin,\n });\n\n const additionalRttByOrigin = new Map<string, number>();\n const serverResponseTimeByOrigin = new Map<string, number>();\n for (const [origin, summary] of responseTimeSummaries.entries()) {\n // Not all origins have usable timing data, we'll default to using no additional latency.\n const rttForOrigin = rttByOrigin.get(origin) || minimumRtt;\n additionalRttByOrigin.set(origin, rttForOrigin - minimumRtt);\n serverResponseTimeByOrigin.set(origin, summary.median);\n }\n\n return {\n rtt: minimumRtt,\n additionalRttByOrigin,\n serverResponseTimeByOrigin,\n };\n }\n\n static analyze(records: Lantern.NetworkRequest[]): Lantern.Simulation.Settings['networkAnalysis']|null {\n const throughput = NetworkAnalyzer.estimateThroughput(records);\n if (throughput === null) {\n return null;\n }\n\n return {\n throughput,\n ...NetworkAnalyzer.computeRTTAndServerResponseTime(records),\n };\n }\n\n static findResourceForUrl<T extends Lantern.NetworkRequest>(records: Array<T>, resourceUrl: string): T|undefined {\n // equalWithExcludedFragments is expensive, so check that the resourceUrl starts with the request url first\n return records.find(\n request => resourceUrl.startsWith(request.url) && UrlUtils.equalWithExcludedFragments(request.url, resourceUrl),\n );\n }\n\n static findLastDocumentForUrl<T extends Lantern.NetworkRequest>(records: Array<T>, resourceUrl: string): T|undefined {\n // equalWithExcludedFragments is expensive, so check that the resourceUrl starts with the request url first\n const matchingRequests = records.filter(\n request => request.resourceType === 'Document' && !request.failed &&\n // Note: `request.url` should never have a fragment, else this optimization gives wrong results.\n resourceUrl.startsWith(request.url) && UrlUtils.equalWithExcludedFragments(request.url, resourceUrl),\n );\n return matchingRequests[matchingRequests.length - 1];\n }\n\n /**\n * Resolves redirect chain given a main document.\n * See: {@link NetworkAnalyzer.findLastDocumentForUrl} for how to retrieve main document.\n */\n static resolveRedirects<T extends Lantern.NetworkRequest>(request: T): T {\n while (request.redirectDestination) {\n request = request.redirectDestination as T;\n }\n return request;\n }\n}\n\nexport {NetworkAnalyzer};\n"]}
@@ -33,7 +33,8 @@
33
33
  "../../../../../../../../front_end/models/trace/lantern/core/NetworkAnalyzer.ts",
34
34
  "../../../../../../../../front_end/legacy/legacy-defs.d.ts",
35
35
  "../../../../../../../../front_end/global_typings/global_defs.d.ts",
36
- "../../../../../../../../node_modules/@types/filesystem/index.d.ts"
36
+ "../../../../../../../../node_modules/@types/filesystem/index.d.ts",
37
+ "../../../../../../../../node_modules/@types/wicg-task-scheduling/index.d.ts"
37
38
  ],
38
39
  "references": [
39
40
  {
@@ -32,7 +32,8 @@
32
32
  "../../../../../../../../front_end/models/trace/lantern/core/core.ts",
33
33
  "../../../../../../../../front_end/legacy/legacy-defs.d.ts",
34
34
  "../../../../../../../../front_end/global_typings/global_defs.d.ts",
35
- "../../../../../../../../node_modules/@types/filesystem/index.d.ts"
35
+ "../../../../../../../../node_modules/@types/filesystem/index.d.ts",
36
+ "../../../../../../../../node_modules/@types/wicg-task-scheduling/index.d.ts"
36
37
  ],
37
38
  "references": [
38
39
  {
@@ -32,7 +32,8 @@
32
32
  "../../../../../../../front_end/models/trace/lantern/lantern.ts",
33
33
  "../../../../../../../front_end/legacy/legacy-defs.d.ts",
34
34
  "../../../../../../../front_end/global_typings/global_defs.d.ts",
35
- "../../../../../../../node_modules/@types/filesystem/index.d.ts"
35
+ "../../../../../../../node_modules/@types/filesystem/index.d.ts",
36
+ "../../../../../../../node_modules/@types/wicg-task-scheduling/index.d.ts"
36
37
  ],
37
38
  "references": [
38
39
  {
@@ -440,7 +440,6 @@ class PageDependencyGraph {
440
440
  serverResponseTime: r.serverResponseTime,
441
441
  }))
442
442
  .filter(r => !r.fromWorker);
443
- // eslint-disable-next-line no-unused-vars
444
443
  const debug = requests;
445
444
  // Set breakpoint here.
446
445
  // Copy `debug` and compare with https://www.diffchecker.com/text-compare/
@@ -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 // eslint-disable-next-line no-unused-vars\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 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"]}
@@ -32,7 +32,8 @@
32
32
  "../../../../../../../../front_end/models/trace/lantern/graph/graph.ts",
33
33
  "../../../../../../../../front_end/legacy/legacy-defs.d.ts",
34
34
  "../../../../../../../../front_end/global_typings/global_defs.d.ts",
35
- "../../../../../../../../node_modules/@types/filesystem/index.d.ts"
35
+ "../../../../../../../../node_modules/@types/filesystem/index.d.ts",
36
+ "../../../../../../../../node_modules/@types/wicg-task-scheduling/index.d.ts"
36
37
  ],
37
38
  "references": [
38
39
  {
@@ -35,7 +35,8 @@
35
35
  "../../../../../../../../front_end/models/trace/lantern/graph/PageDependencyGraph.ts",
36
36
  "../../../../../../../../front_end/legacy/legacy-defs.d.ts",
37
37
  "../../../../../../../../front_end/global_typings/global_defs.d.ts",
38
- "../../../../../../../../node_modules/@types/filesystem/index.d.ts"
38
+ "../../../../../../../../node_modules/@types/filesystem/index.d.ts",
39
+ "../../../../../../../../node_modules/@types/wicg-task-scheduling/index.d.ts"
39
40
  ],
40
41
  "references": [
41
42
  {
@@ -31,7 +31,8 @@
31
31
  "files": [
32
32
  "../../../../../../../front_end/legacy/legacy-defs.d.ts",
33
33
  "../../../../../../../front_end/global_typings/global_defs.d.ts",
34
- "../../../../../../../node_modules/@types/filesystem/index.d.ts"
34
+ "../../../../../../../node_modules/@types/filesystem/index.d.ts",
35
+ "../../../../../../../node_modules/@types/wicg-task-scheduling/index.d.ts"
35
36
  ],
36
37
  "references": [
37
38
  {
@@ -32,7 +32,8 @@
32
32
  "../../../../../../../../front_end/models/trace/lantern/metrics/metrics.ts",
33
33
  "../../../../../../../../front_end/legacy/legacy-defs.d.ts",
34
34
  "../../../../../../../../front_end/global_typings/global_defs.d.ts",
35
- "../../../../../../../../node_modules/@types/filesystem/index.d.ts"
35
+ "../../../../../../../../node_modules/@types/filesystem/index.d.ts",
36
+ "../../../../../../../../node_modules/@types/wicg-task-scheduling/index.d.ts"
36
37
  ],
37
38
  "references": [
38
39
  {
@@ -39,7 +39,8 @@
39
39
  "../../../../../../../../front_end/models/trace/lantern/metrics/TotalBlockingTime.ts",
40
40
  "../../../../../../../../front_end/legacy/legacy-defs.d.ts",
41
41
  "../../../../../../../../front_end/global_typings/global_defs.d.ts",
42
- "../../../../../../../../node_modules/@types/filesystem/index.d.ts"
42
+ "../../../../../../../../node_modules/@types/filesystem/index.d.ts",
43
+ "../../../../../../../../node_modules/@types/wicg-task-scheduling/index.d.ts"
43
44
  ],
44
45
  "references": [
45
46
  {
@@ -9,8 +9,8 @@ declare class DNSCache {
9
9
  rtt: number;
10
10
  });
11
11
  getTimeUntilResolution(request: Lantern.NetworkRequest, options?: {
12
- requestedAt: number;
13
- shouldUpdateCache: boolean;
12
+ requestedAt?: number;
13
+ shouldUpdateCache?: boolean;
14
14
  }): number;
15
15
  updateCacheResolvedAtIfNeeded(request: Lantern.NetworkRequest, resolvedAt: number): void;
16
16
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"DNSCache.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/simulation/DNSCache.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAI7B,wGAAwG;AACxG,yHAAyH;AACzH,yHAAyH;AACzH,mGAAmG;AACnG,oGAAoG;AACpG,MAAM,6BAA6B,GAAG,CAAC,CAAC;AAExC,MAAM,QAAQ;IACZ,MAAM,CAAC,aAAa,GAAG,6BAA6B,CAAC;IAErD,GAAG,CAAS;IACZ,mBAAmB,CAAoC;IAEvD,YAAY,EAAC,GAAG,EAAgB;QAC9B,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,mBAAmB,GAAG,IAAI,GAAG,EAAE,CAAC;IACvC,CAAC;IAED,sBAAsB,CAAC,OAA+B,EAAE,OAA2D;QAEjH,MAAM,EAAC,WAAW,GAAG,CAAC,EAAE,iBAAiB,GAAG,KAAK,EAAC,GAAG,OAAO,IAAI,EAAE,CAAC;QAEnE,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC;QACtC,MAAM,UAAU,GAAG,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACxD,IAAI,iBAAiB,GAAG,IAAI,CAAC,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC;QAC1D,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,yBAAyB,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,GAAG,WAAW,EAAE,CAAC,CAAC,CAAC;YACnF,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,yBAAyB,EAAE,iBAAiB,CAAC,CAAC;QAC7E,CAAC;QAED,MAAM,UAAU,GAAG,WAAW,GAAG,iBAAiB,CAAC;QACnD,IAAI,iBAAiB,EAAE,CAAC;YACtB,IAAI,CAAC,6BAA6B,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC1D,CAAC;QAED,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IAED,6BAA6B,CAAC,OAA+B,EAAE,UAAkB;QAC/E,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC;QACtC,MAAM,UAAU,GAAG,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAC,UAAU,EAAC,CAAC;QACxE,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QACpE,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACnD,CAAC;IAED;;;OAGG;IACH,aAAa,CAAC,MAAc,EAAE,UAAkB;QAC9C,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,EAAE,EAAC,UAAU,EAAC,CAAC,CAAC;IACrD,CAAC;;AAGH,OAAO,EAAC,QAAQ,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 * as Lantern from '../types/types.js';\n\n// A DNS lookup will usually take ~1-2 roundtrips of connection latency plus the extra DNS routing time.\n// Example: https://www.webpagetest.org/result/180703_3A_e33ec79747c002ed4d7bcbfc81462203/1/details/#waterfall_view_step1\n// Example: https://www.webpagetest.org/result/180707_1M_89673eb633b5d98386de95dfcf9b33d5/1/details/#waterfall_view_step1\n// DNS is highly variable though, many times it's a little more than 1, but can easily be 4-5x RTT.\n// We'll use 2 since it seems to give the most accurate results on average, but this can be tweaked.\nconst DNS_RESOLUTION_RTT_MULTIPLIER = 2;\n\nclass DNSCache {\n static rttMultiplier = DNS_RESOLUTION_RTT_MULTIPLIER;\n\n rtt: number;\n resolvedDomainNames: Map<string, {resolvedAt: number}>;\n\n constructor({rtt}: {rtt: number}) {\n this.rtt = rtt;\n this.resolvedDomainNames = new Map();\n }\n\n getTimeUntilResolution(request: Lantern.NetworkRequest, options?: {requestedAt: number, shouldUpdateCache: boolean}):\n number {\n const {requestedAt = 0, shouldUpdateCache = false} = options || {};\n\n const domain = request.parsedURL.host;\n const cacheEntry = this.resolvedDomainNames.get(domain);\n let timeUntilResolved = this.rtt * DNSCache.rttMultiplier;\n if (cacheEntry) {\n const timeUntilCachedIsResolved = Math.max(cacheEntry.resolvedAt - requestedAt, 0);\n timeUntilResolved = Math.min(timeUntilCachedIsResolved, timeUntilResolved);\n }\n\n const resolvedAt = requestedAt + timeUntilResolved;\n if (shouldUpdateCache) {\n this.updateCacheResolvedAtIfNeeded(request, resolvedAt);\n }\n\n return timeUntilResolved;\n }\n\n updateCacheResolvedAtIfNeeded(request: Lantern.NetworkRequest, resolvedAt: number): void {\n const domain = request.parsedURL.host;\n const cacheEntry = this.resolvedDomainNames.get(domain) || {resolvedAt};\n cacheEntry.resolvedAt = Math.min(cacheEntry.resolvedAt, resolvedAt);\n this.resolvedDomainNames.set(domain, cacheEntry);\n }\n\n /**\n * Forcefully sets the DNS resolution time for a request.\n * Useful for testing and alternate execution simulations.\n */\n setResolvedAt(domain: string, resolvedAt: number): void {\n this.resolvedDomainNames.set(domain, {resolvedAt});\n }\n}\n\nexport {DNSCache};\n"]}
1
+ {"version":3,"file":"DNSCache.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/simulation/DNSCache.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAI7B,wGAAwG;AACxG,yHAAyH;AACzH,yHAAyH;AACzH,mGAAmG;AACnG,oGAAoG;AACpG,MAAM,6BAA6B,GAAG,CAAC,CAAC;AAExC,MAAM,QAAQ;IACZ,MAAM,CAAC,aAAa,GAAG,6BAA6B,CAAC;IAErD,GAAG,CAAS;IACZ,mBAAmB,CAAoC;IAEvD,YAAY,EAAC,GAAG,EAAgB;QAC9B,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,mBAAmB,GAAG,IAAI,GAAG,EAAE,CAAC;IACvC,CAAC;IAED,sBAAsB,CAClB,OAA+B,EAAE,OAA6D;QAChG,MAAM,EAAC,WAAW,GAAG,CAAC,EAAE,iBAAiB,GAAG,KAAK,EAAC,GAAG,OAAO,IAAI,EAAE,CAAC;QAEnE,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC;QACtC,MAAM,UAAU,GAAG,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACxD,IAAI,iBAAiB,GAAG,IAAI,CAAC,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC;QAC1D,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,yBAAyB,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,GAAG,WAAW,EAAE,CAAC,CAAC,CAAC;YACnF,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,yBAAyB,EAAE,iBAAiB,CAAC,CAAC;QAC7E,CAAC;QAED,MAAM,UAAU,GAAG,WAAW,GAAG,iBAAiB,CAAC;QACnD,IAAI,iBAAiB,EAAE,CAAC;YACtB,IAAI,CAAC,6BAA6B,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC1D,CAAC;QAED,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IAED,6BAA6B,CAAC,OAA+B,EAAE,UAAkB;QAC/E,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC;QACtC,MAAM,UAAU,GAAG,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAC,UAAU,EAAC,CAAC;QACxE,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QACpE,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACnD,CAAC;IAED;;;OAGG;IACH,aAAa,CAAC,MAAc,EAAE,UAAkB;QAC9C,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,EAAE,EAAC,UAAU,EAAC,CAAC,CAAC;IACrD,CAAC;;AAGH,OAAO,EAAC,QAAQ,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 * as Lantern from '../types/types.js';\n\n// A DNS lookup will usually take ~1-2 roundtrips of connection latency plus the extra DNS routing time.\n// Example: https://www.webpagetest.org/result/180703_3A_e33ec79747c002ed4d7bcbfc81462203/1/details/#waterfall_view_step1\n// Example: https://www.webpagetest.org/result/180707_1M_89673eb633b5d98386de95dfcf9b33d5/1/details/#waterfall_view_step1\n// DNS is highly variable though, many times it's a little more than 1, but can easily be 4-5x RTT.\n// We'll use 2 since it seems to give the most accurate results on average, but this can be tweaked.\nconst DNS_RESOLUTION_RTT_MULTIPLIER = 2;\n\nclass DNSCache {\n static rttMultiplier = DNS_RESOLUTION_RTT_MULTIPLIER;\n\n rtt: number;\n resolvedDomainNames: Map<string, {resolvedAt: number}>;\n\n constructor({rtt}: {rtt: number}) {\n this.rtt = rtt;\n this.resolvedDomainNames = new Map();\n }\n\n getTimeUntilResolution(\n request: Lantern.NetworkRequest, options?: {requestedAt?: number, shouldUpdateCache?: boolean}): number {\n const {requestedAt = 0, shouldUpdateCache = false} = options || {};\n\n const domain = request.parsedURL.host;\n const cacheEntry = this.resolvedDomainNames.get(domain);\n let timeUntilResolved = this.rtt * DNSCache.rttMultiplier;\n if (cacheEntry) {\n const timeUntilCachedIsResolved = Math.max(cacheEntry.resolvedAt - requestedAt, 0);\n timeUntilResolved = Math.min(timeUntilCachedIsResolved, timeUntilResolved);\n }\n\n const resolvedAt = requestedAt + timeUntilResolved;\n if (shouldUpdateCache) {\n this.updateCacheResolvedAtIfNeeded(request, resolvedAt);\n }\n\n return timeUntilResolved;\n }\n\n updateCacheResolvedAtIfNeeded(request: Lantern.NetworkRequest, resolvedAt: number): void {\n const domain = request.parsedURL.host;\n const cacheEntry = this.resolvedDomainNames.get(domain) || {resolvedAt};\n cacheEntry.resolvedAt = Math.min(cacheEntry.resolvedAt, resolvedAt);\n this.resolvedDomainNames.set(domain, cacheEntry);\n }\n\n /**\n * Forcefully sets the DNS resolution time for a request.\n * Useful for testing and alternate execution simulations.\n */\n setResolvedAt(domain: string, resolvedAt: number): void {\n this.resolvedDomainNames.set(domain, {resolvedAt});\n }\n}\n\nexport {DNSCache};\n"]}
@@ -32,7 +32,8 @@
32
32
  "../../../../../../../../front_end/models/trace/lantern/simulation/simulation.ts",
33
33
  "../../../../../../../../front_end/legacy/legacy-defs.d.ts",
34
34
  "../../../../../../../../front_end/global_typings/global_defs.d.ts",
35
- "../../../../../../../../node_modules/@types/filesystem/index.d.ts"
35
+ "../../../../../../../../node_modules/@types/filesystem/index.d.ts",
36
+ "../../../../../../../../node_modules/@types/wicg-task-scheduling/index.d.ts"
36
37
  ],
37
38
  "references": [
38
39
  {
@@ -37,7 +37,8 @@
37
37
  "../../../../../../../../front_end/models/trace/lantern/simulation/TCPConnection.ts",
38
38
  "../../../../../../../../front_end/legacy/legacy-defs.d.ts",
39
39
  "../../../../../../../../front_end/global_typings/global_defs.d.ts",
40
- "../../../../../../../../node_modules/@types/filesystem/index.d.ts"
40
+ "../../../../../../../../node_modules/@types/filesystem/index.d.ts",
41
+ "../../../../../../../../node_modules/@types/wicg-task-scheduling/index.d.ts"
41
42
  ],
42
43
  "references": [
43
44
  {