@paulirish/trace_engine 0.0.26 → 0.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/models/trace/LanternComputationData.d.ts +4 -4
- package/models/trace/LanternComputationData.js +4 -4
- package/models/trace/LanternComputationData.js.map +1 -1
- package/models/trace/lantern/core/LanternError.d.ts +3 -0
- package/models/trace/lantern/core/LanternError.js +7 -0
- package/models/trace/lantern/core/LanternError.js.map +1 -0
- package/models/trace/lantern/core/NetworkAnalyzer.d.ts +112 -0
- package/models/trace/lantern/core/NetworkAnalyzer.js +486 -0
- package/models/trace/lantern/core/NetworkAnalyzer.js.map +1 -0
- package/models/trace/lantern/core/bundle-tsconfig.json +1 -0
- package/models/trace/lantern/core/core-tsconfig.json +43 -0
- package/models/trace/lantern/core/core.d.ts +2 -0
- package/models/trace/lantern/core/core.js +6 -0
- package/models/trace/lantern/core/core.js.map +1 -0
- package/models/trace/lantern/core/devtools_entrypoint-bundle-typescript-tsconfig.json +42 -0
- package/models/trace/lantern/graph/BaseNode.d.ts +91 -0
- package/models/trace/lantern/graph/BaseNode.js +268 -0
- package/models/trace/lantern/graph/BaseNode.js.map +1 -0
- package/models/trace/lantern/graph/CPUNode.d.ts +24 -0
- package/models/trace/lantern/graph/CPUNode.js +64 -0
- package/models/trace/lantern/graph/CPUNode.js.map +1 -0
- package/models/trace/lantern/graph/NetworkNode.d.ts +22 -0
- package/models/trace/lantern/graph/NetworkNode.js +83 -0
- package/models/trace/lantern/graph/NetworkNode.js.map +1 -0
- package/models/trace/lantern/graph/PageDependencyGraph.d.ts +43 -0
- package/models/trace/lantern/graph/PageDependencyGraph.js +509 -0
- package/models/trace/lantern/graph/PageDependencyGraph.js.map +1 -0
- package/models/trace/lantern/graph/bundle-tsconfig.json +1 -0
- package/models/trace/lantern/graph/devtools_entrypoint-bundle-typescript-tsconfig.json +42 -0
- package/models/trace/lantern/graph/graph-tsconfig.json +48 -0
- package/models/trace/lantern/graph/graph.d.ts +4 -0
- package/models/trace/lantern/graph/graph.js +8 -0
- package/models/trace/lantern/graph/graph.js.map +1 -0
- package/models/trace/lantern/lantern-tsconfig.json +13 -24
- package/models/trace/lantern/lantern.d.ts +6 -29
- package/models/trace/lantern/lantern.js +6 -29
- package/models/trace/lantern/lantern.js.map +1 -1
- package/models/trace/lantern/metrics/FirstContentfulPaint.d.ts +10 -12
- package/models/trace/lantern/metrics/FirstContentfulPaint.js +3 -3
- package/models/trace/lantern/metrics/FirstContentfulPaint.js.map +1 -1
- package/models/trace/lantern/metrics/Interactive.d.ts +9 -9
- package/models/trace/lantern/metrics/Interactive.js +4 -5
- package/models/trace/lantern/metrics/Interactive.js.map +1 -1
- package/models/trace/lantern/metrics/LargestContentfulPaint.d.ts +10 -9
- package/models/trace/lantern/metrics/LargestContentfulPaint.js +4 -5
- package/models/trace/lantern/metrics/LargestContentfulPaint.js.map +1 -1
- package/models/trace/lantern/metrics/MaxPotentialFID.d.ts +9 -9
- package/models/trace/lantern/metrics/MaxPotentialFID.js +3 -4
- package/models/trace/lantern/metrics/MaxPotentialFID.js.map +1 -1
- package/models/trace/lantern/metrics/Metric.d.ts +31 -13
- package/models/trace/lantern/metrics/Metric.js +2 -3
- package/models/trace/lantern/metrics/Metric.js.map +1 -1
- package/models/trace/lantern/metrics/SpeedIndex.d.ts +10 -10
- package/models/trace/lantern/metrics/SpeedIndex.js +3 -4
- package/models/trace/lantern/metrics/SpeedIndex.js.map +1 -1
- package/models/trace/lantern/metrics/TotalBlockingTime.d.ts +9 -9
- package/models/trace/lantern/metrics/TotalBlockingTime.js +3 -4
- package/models/trace/lantern/metrics/TotalBlockingTime.js.map +1 -1
- package/models/trace/lantern/metrics/bundle-tsconfig.json +1 -0
- package/models/trace/lantern/metrics/devtools_entrypoint-bundle-typescript-tsconfig.json +42 -0
- package/models/trace/lantern/metrics/metrics-tsconfig.json +58 -0
- package/models/trace/lantern/metrics/metrics.d.ts +7 -14
- package/models/trace/lantern/metrics/metrics.js +7 -7
- package/models/trace/lantern/metrics/metrics.js.map +1 -1
- package/models/trace/lantern/simulation/ConnectionPool.d.ts +1 -1
- package/models/trace/lantern/simulation/ConnectionPool.js +3 -3
- package/models/trace/lantern/simulation/ConnectionPool.js.map +1 -1
- package/models/trace/lantern/simulation/DNSCache.d.ts +1 -1
- package/models/trace/lantern/simulation/DNSCache.js.map +1 -1
- package/models/trace/lantern/simulation/SimulationTimingMap.d.ts +15 -17
- package/models/trace/lantern/simulation/SimulationTimingMap.js +2 -2
- package/models/trace/lantern/simulation/SimulationTimingMap.js.map +1 -1
- package/models/trace/lantern/simulation/Simulator.d.ts +24 -22
- package/models/trace/lantern/simulation/Simulator.js +10 -10
- package/models/trace/lantern/simulation/Simulator.js.map +1 -1
- package/models/trace/lantern/simulation/bundle-tsconfig.json +1 -0
- package/models/trace/lantern/simulation/devtools_entrypoint-bundle-typescript-tsconfig.json +42 -0
- package/models/trace/lantern/simulation/simulation-tsconfig.json +50 -0
- package/models/trace/lantern/simulation/simulation.d.ts +6 -21
- package/models/trace/lantern/simulation/simulation.js +6 -7
- package/models/trace/lantern/simulation/simulation.js.map +1 -1
- package/models/trace/lantern/types/{lantern.d.ts → Lantern.d.ts} +21 -27
- package/models/trace/lantern/types/Lantern.js +24 -0
- package/models/trace/lantern/types/Lantern.js.map +1 -0
- package/models/trace/lantern/types/bundle-tsconfig.json +1 -0
- package/models/trace/lantern/types/devtools_entrypoint-bundle-typescript-tsconfig.json +42 -0
- package/models/trace/lantern/types/types-tsconfig.json +42 -0
- package/models/trace/lantern/types/types.d.ts +1 -0
- package/models/trace/lantern/types/{lantern.js → types.js} +2 -2
- package/models/trace/lantern/types/types.js.map +1 -0
- package/package.json +1 -1
- package/models/trace/lantern/types/lantern.js.map +0 -1
|
@@ -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,IAAI,CAAS;IACb,oBAAoB,CAAoC;IAExD,YAAY,EAAC,GAAG,EAAgB;QAC9B,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;QAChB,IAAI,CAAC,oBAAoB,GAAG,IAAI,GAAG,EAAE,CAAC;IACxC,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,oBAAoB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACzD,IAAI,iBAAiB,GAAG,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC;QAC3D,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,8BAA8B,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC3D,CAAC;QAED,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IAED,8BAA8B,CAAC,OAA+B,EAAE,UAAkB;QAChF,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC;QACtC,MAAM,UAAU,GAAG,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAC,UAAU,EAAC,CAAC;QACzE,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QACpE,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACpD,CAAC;IAED;;;OAGG;IACH,aAAa,CAAC,MAAc,EAAE,UAAkB;QAC9C,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,MAAM,EAAE,EAAC,UAAU,EAAC,CAAC,CAAC;IACtD,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/
|
|
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,IAAI,CAAS;IACb,oBAAoB,CAAoC;IAExD,YAAY,EAAC,GAAG,EAAgB;QAC9B,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;QAChB,IAAI,CAAC,oBAAoB,GAAG,IAAI,GAAG,EAAE,CAAC;IACxC,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,oBAAoB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACzD,IAAI,iBAAiB,GAAG,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC;QAC3D,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,8BAA8B,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC3D,CAAC;QAED,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IAED,8BAA8B,CAAC,OAA+B,EAAE,UAAkB;QAChF,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC;QACtC,MAAM,UAAU,GAAG,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAC,UAAU,EAAC,CAAC;QACzE,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QACpE,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACpD,CAAC;IAED;;;OAGG;IACH,aAAa,CAAC,MAAc,EAAE,UAAkB;QAC9C,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,MAAM,EAAE,EAAC,UAAU,EAAC,CAAC,CAAC;IACtD,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"]}
|
|
@@ -5,9 +5,7 @@
|
|
|
5
5
|
* through the different simulation phases. Methods here ensure that the invariants of simulation hold
|
|
6
6
|
* as nodes are queued, partially simulated, and completed.
|
|
7
7
|
*/
|
|
8
|
-
import
|
|
9
|
-
import { type CPUNode } from '../CPUNode.js';
|
|
10
|
-
import { type NetworkNode } from '../NetworkNode.js';
|
|
8
|
+
import * as Graph from '../graph/graph.js';
|
|
11
9
|
interface NodeTimingComplete {
|
|
12
10
|
startTime: number;
|
|
13
11
|
endTime: number;
|
|
@@ -35,37 +33,37 @@ export interface ConnectionTiming {
|
|
|
35
33
|
timeToFirstByte: number;
|
|
36
34
|
}
|
|
37
35
|
declare class SimulatorTimingMap {
|
|
38
|
-
_nodeTimings: Map<Node, NodeTimingData>;
|
|
36
|
+
_nodeTimings: Map<Graph.Node, NodeTimingData>;
|
|
39
37
|
constructor();
|
|
40
|
-
getNodes(): Node[];
|
|
41
|
-
setReadyToStart(node: Node, values: {
|
|
38
|
+
getNodes(): Graph.Node[];
|
|
39
|
+
setReadyToStart(node: Graph.Node, values: {
|
|
42
40
|
queuedTime: number;
|
|
43
41
|
}): void;
|
|
44
|
-
setInProgress(node: Node, values: {
|
|
42
|
+
setInProgress(node: Graph.Node, values: {
|
|
45
43
|
startTime: number;
|
|
46
44
|
}): void;
|
|
47
|
-
setCompleted(node: Node, values: {
|
|
45
|
+
setCompleted(node: Graph.Node, values: {
|
|
48
46
|
endTime: number;
|
|
49
47
|
connectionTiming?: ConnectionTiming;
|
|
50
48
|
}): void;
|
|
51
|
-
setCpu(node: CPUNode, values: {
|
|
49
|
+
setCpu(node: Graph.CPUNode, values: {
|
|
52
50
|
timeElapsed: number;
|
|
53
51
|
}): void;
|
|
54
|
-
setCpuEstimated(node: CPUNode, values: {
|
|
52
|
+
setCpuEstimated(node: Graph.CPUNode, values: {
|
|
55
53
|
estimatedTimeElapsed: number;
|
|
56
54
|
}): void;
|
|
57
|
-
setNetwork(node: NetworkNode, values: {
|
|
55
|
+
setNetwork(node: Graph.NetworkNode, values: {
|
|
58
56
|
timeElapsed: number;
|
|
59
57
|
timeElapsedOvershoot: number;
|
|
60
58
|
bytesDownloaded: number;
|
|
61
59
|
}): void;
|
|
62
|
-
setNetworkEstimated(node: NetworkNode, values: {
|
|
60
|
+
setNetworkEstimated(node: Graph.NetworkNode, values: {
|
|
63
61
|
estimatedTimeElapsed: number;
|
|
64
62
|
}): void;
|
|
65
|
-
getQueued(node: Node): NodeTimingData;
|
|
66
|
-
getCpuStarted(node: CPUNode): CpuNodeTimingStarted;
|
|
67
|
-
getNetworkStarted(node: NetworkNode): NetworkNodeTimingStarted;
|
|
68
|
-
getInProgress(node: Node): CpuNodeTimingInProgress | NetworkNodeTimingInProgress;
|
|
69
|
-
getCompleted(node: Node): CpuNodeTimingComplete | NetworkNodeTimingComplete;
|
|
63
|
+
getQueued(node: Graph.Node): NodeTimingData;
|
|
64
|
+
getCpuStarted(node: Graph.CPUNode): CpuNodeTimingStarted;
|
|
65
|
+
getNetworkStarted(node: Graph.NetworkNode): NetworkNodeTimingStarted;
|
|
66
|
+
getInProgress(node: Graph.Node): CpuNodeTimingInProgress | NetworkNodeTimingInProgress;
|
|
67
|
+
getCompleted(node: Graph.Node): CpuNodeTimingComplete | NetworkNodeTimingComplete;
|
|
70
68
|
}
|
|
71
69
|
export { SimulatorTimingMap };
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* through the different simulation phases. Methods here ensure that the invariants of simulation hold
|
|
9
9
|
* as nodes are queued, partially simulated, and completed.
|
|
10
10
|
*/
|
|
11
|
-
import
|
|
11
|
+
import * as Graph from '../graph/graph.js';
|
|
12
12
|
class SimulatorTimingMap {
|
|
13
13
|
_nodeTimings;
|
|
14
14
|
constructor() {
|
|
@@ -26,7 +26,7 @@ class SimulatorTimingMap {
|
|
|
26
26
|
startTime: values.startTime,
|
|
27
27
|
timeElapsed: 0,
|
|
28
28
|
};
|
|
29
|
-
this._nodeTimings.set(node, node.type === BaseNode.types.NETWORK ? { ...nodeTiming, timeElapsedOvershoot: 0, bytesDownloaded: 0 } :
|
|
29
|
+
this._nodeTimings.set(node, node.type === Graph.BaseNode.types.NETWORK ? { ...nodeTiming, timeElapsedOvershoot: 0, bytesDownloaded: 0 } :
|
|
30
30
|
nodeTiming);
|
|
31
31
|
}
|
|
32
32
|
setCompleted(node, values) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SimulationTimingMap.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/simulation/SimulationTimingMap.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B;;;;;;GAMG;AAEH,OAAO,EAAC,QAAQ,EAAY,MAAM,gBAAgB,CAAC;AAqCnD,MAAM,kBAAkB;IACtB,YAAY,CAA4B;IAExC;QACE,IAAI,CAAC,YAAY,GAAG,IAAI,GAAG,EAAwB,CAAC;IACtD,CAAC;IAED,QAAQ;QACN,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,eAAe,CAAC,IAAU,EAAE,MAA4B;QACtD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,aAAa,CAAC,IAAU,EAAE,MAA2B;QACnD,MAAM,UAAU,GAAG;YACjB,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YACvB,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,WAAW,EAAE,CAAC;SACf,CAAC;QAEF,IAAI,CAAC,YAAY,CAAC,GAAG,CACjB,IAAI,EACJ,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAC,GAAG,UAAU,EAAE,oBAAoB,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAC,CAAC,CAAC;YAC9D,UAAU,CACpD,CAAC;IACJ,CAAC;IAED,YAAY,CAAC,IAAU,EAAE,MAA8D;QACrF,MAAM,UAAU,GAAG;YACjB,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;YAC3B,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;SAC1C,CAAC;QAEF,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,CAAC,IAAa,EAAE,MAA6B;QACjD,MAAM,UAAU,GAAG;YACjB,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;YAC3B,WAAW,EAAE,MAAM,CAAC,WAAW;SAChC,CAAC;QAEF,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC1C,CAAC;IAED,eAAe,CAAC,IAAa,EAAE,MAAsC;QACnE,MAAM,UAAU,GAAG;YACjB,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;YAC3B,oBAAoB,EAAE,MAAM,CAAC,oBAAoB;SAClD,CAAC;QAEF,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC1C,CAAC;IAED,UAAU,CAAC,IAAiB,EAAE,MAAoF;QAEhH,MAAM,UAAU,GAAG;YACjB,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC;YAC/B,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,oBAAoB,EAAE,MAAM,CAAC,oBAAoB;YACjD,eAAe,EAAE,MAAM,CAAC,eAAe;SACxC,CAAC;QAEF,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC1C,CAAC;IAED,mBAAmB,CAAC,IAAiB,EAAE,MAAsC;QAC3E,MAAM,UAAU,GAAG;YACjB,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC;YAC/B,oBAAoB,EAAE,MAAM,CAAC,oBAAoB;SAClD,CAAC;QAEF,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC1C,CAAC;IAED,SAAS,CAAC,IAAU;QAClB,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,EAAE,iBAAiB,CAAC,CAAC;QACpD,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,aAAa,CAAC,IAAa;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,EAAE,iBAAiB,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,CAAC,CAAC,WAAW,IAAI,MAAM,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,EAAE,kBAAkB,CAAC,CAAC;QACrD,CAAC;QACD,IAAI,iBAAiB,IAAI,MAAM,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,EAAE,mBAAmB,CAAC,CAAC;QACtD,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,iBAAiB,CAAC,IAAiB;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,EAAE,iBAAiB,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,CAAC,CAAC,WAAW,IAAI,MAAM,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,EAAE,kBAAkB,CAAC,CAAC;QACrD,CAAC;QACD,IAAI,CAAC,CAAC,iBAAiB,IAAI,MAAM,CAAC,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,EAAE,mBAAmB,CAAC,CAAC;QACtD,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,aAAa,CAAC,IAAU;QACtB,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,EAAE,iBAAiB,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,CAAC,CAAC,WAAW,IAAI,MAAM,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,EAAE,kBAAkB,CAAC,CAAC;QACrD,CAAC;QACD,IAAI,CAAC,CAAC,sBAAsB,IAAI,MAAM,CAAC,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,EAAE,sBAAsB,CAAC,CAAC;QACzD,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,YAAY,CAAC,IAAU;QACrB,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,EAAE,iBAAiB,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,CAAC,CAAC,WAAW,IAAI,MAAM,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,EAAE,kBAAkB,CAAC,CAAC;QACrD,CAAC;QACD,IAAI,CAAC,CAAC,sBAAsB,IAAI,MAAM,CAAC,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,EAAE,sBAAsB,CAAC,CAAC;QACzD,CAAC;QACD,IAAI,CAAC,CAAC,SAAS,IAAI,MAAM,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,EAAE,oBAAoB,CAAC,CAAC;QACvD,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAED,OAAO,EAAC,kBAAkB,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\n/**\n * @fileoverview\n *\n * This class encapsulates the type-related validation logic for moving timing information for nodes\n * through the different simulation phases. Methods here ensure that the invariants of simulation hold\n * as nodes are queued, partially simulated, and completed.\n */\n\nimport {BaseNode, type Node} from '../BaseNode.js';\nimport {type CPUNode} from '../CPUNode.js';\nimport {type NetworkNode} from '../NetworkNode.js';\n\ninterface NodeTimingComplete {\n startTime: number;\n endTime: number;\n queuedTime: number;\n estimatedTimeElapsed: number;\n timeElapsed: number;\n timeElapsedOvershoot: number;\n bytesDownloaded: number;\n}\n\ntype NodeTimingQueued = Pick<NodeTimingComplete, 'queuedTime'>;\n\ntype CpuNodeTimingStarted = NodeTimingQueued&Pick<NodeTimingComplete, 'startTime'|'timeElapsed'>;\ntype NetworkNodeTimingStarted = CpuNodeTimingStarted&Pick<NodeTimingComplete, 'timeElapsedOvershoot'|'bytesDownloaded'>;\n\ntype CpuNodeTimingInProgress = CpuNodeTimingStarted&Pick<NodeTimingComplete, 'estimatedTimeElapsed'>;\ntype NetworkNodeTimingInProgress = NetworkNodeTimingStarted&Pick<NodeTimingComplete, 'estimatedTimeElapsed'>;\n\nexport type CpuNodeTimingComplete = CpuNodeTimingInProgress&Pick<NodeTimingComplete, 'endTime'>;\nexport type NetworkNodeTimingComplete =\n NetworkNodeTimingInProgress&Pick<NodeTimingComplete, 'endTime'>&{connectionTiming: ConnectionTiming};\nexport type CompleteNodeTiming = CpuNodeTimingComplete|NetworkNodeTimingComplete;\n\ntype NodeTimingData = NodeTimingQueued|CpuNodeTimingStarted|NetworkNodeTimingStarted|CpuNodeTimingInProgress|\n NetworkNodeTimingInProgress|CpuNodeTimingComplete|NetworkNodeTimingComplete;\n\nexport interface ConnectionTiming {\n dnsResolutionTime?: number;\n connectionTime?: number;\n sslTime?: number;\n timeToFirstByte: number;\n}\n\nclass SimulatorTimingMap {\n _nodeTimings: Map<Node, NodeTimingData>;\n\n constructor() {\n this._nodeTimings = new Map<Node, NodeTimingData>();\n }\n\n getNodes(): Node[] {\n return Array.from(this._nodeTimings.keys());\n }\n\n setReadyToStart(node: Node, values: {queuedTime: number}): void {\n this._nodeTimings.set(node, values);\n }\n\n setInProgress(node: Node, values: {startTime: number}): void {\n const nodeTiming = {\n ...this.getQueued(node),\n startTime: values.startTime,\n timeElapsed: 0,\n };\n\n this._nodeTimings.set(\n node,\n node.type === BaseNode.types.NETWORK ? {...nodeTiming, timeElapsedOvershoot: 0, bytesDownloaded: 0} :\n nodeTiming,\n );\n }\n\n setCompleted(node: Node, values: {endTime: number, connectionTiming?: ConnectionTiming}): void {\n const nodeTiming = {\n ...this.getInProgress(node),\n endTime: values.endTime,\n connectionTiming: values.connectionTiming,\n };\n\n this._nodeTimings.set(node, nodeTiming);\n }\n\n setCpu(node: CPUNode, values: {timeElapsed: number}): void {\n const nodeTiming = {\n ...this.getCpuStarted(node),\n timeElapsed: values.timeElapsed,\n };\n\n this._nodeTimings.set(node, nodeTiming);\n }\n\n setCpuEstimated(node: CPUNode, values: {estimatedTimeElapsed: number}): void {\n const nodeTiming = {\n ...this.getCpuStarted(node),\n estimatedTimeElapsed: values.estimatedTimeElapsed,\n };\n\n this._nodeTimings.set(node, nodeTiming);\n }\n\n setNetwork(node: NetworkNode, values: {timeElapsed: number, timeElapsedOvershoot: number, bytesDownloaded: number}):\n void {\n const nodeTiming = {\n ...this.getNetworkStarted(node),\n timeElapsed: values.timeElapsed,\n timeElapsedOvershoot: values.timeElapsedOvershoot,\n bytesDownloaded: values.bytesDownloaded,\n };\n\n this._nodeTimings.set(node, nodeTiming);\n }\n\n setNetworkEstimated(node: NetworkNode, values: {estimatedTimeElapsed: number}): void {\n const nodeTiming = {\n ...this.getNetworkStarted(node),\n estimatedTimeElapsed: values.estimatedTimeElapsed,\n };\n\n this._nodeTimings.set(node, nodeTiming);\n }\n\n getQueued(node: Node): NodeTimingData {\n const timing = this._nodeTimings.get(node);\n if (!timing) {\n throw new Error(`Node ${node.id} not yet queued`);\n }\n return timing;\n }\n\n getCpuStarted(node: CPUNode): CpuNodeTimingStarted {\n const timing = this._nodeTimings.get(node);\n if (!timing) {\n throw new Error(`Node ${node.id} not yet queued`);\n }\n if (!('startTime' in timing)) {\n throw new Error(`Node ${node.id} not yet started`);\n }\n if ('bytesDownloaded' in timing) {\n throw new Error(`Node ${node.id} timing not valid`);\n }\n return timing;\n }\n\n getNetworkStarted(node: NetworkNode): NetworkNodeTimingStarted {\n const timing = this._nodeTimings.get(node);\n if (!timing) {\n throw new Error(`Node ${node.id} not yet queued`);\n }\n if (!('startTime' in timing)) {\n throw new Error(`Node ${node.id} not yet started`);\n }\n if (!('bytesDownloaded' in timing)) {\n throw new Error(`Node ${node.id} timing not valid`);\n }\n return timing;\n }\n\n getInProgress(node: Node): CpuNodeTimingInProgress|NetworkNodeTimingInProgress {\n const timing = this._nodeTimings.get(node);\n if (!timing) {\n throw new Error(`Node ${node.id} not yet queued`);\n }\n if (!('startTime' in timing)) {\n throw new Error(`Node ${node.id} not yet started`);\n }\n if (!('estimatedTimeElapsed' in timing)) {\n throw new Error(`Node ${node.id} not yet in progress`);\n }\n return timing;\n }\n\n getCompleted(node: Node): CpuNodeTimingComplete|NetworkNodeTimingComplete {\n const timing = this._nodeTimings.get(node);\n if (!timing) {\n throw new Error(`Node ${node.id} not yet queued`);\n }\n if (!('startTime' in timing)) {\n throw new Error(`Node ${node.id} not yet started`);\n }\n if (!('estimatedTimeElapsed' in timing)) {\n throw new Error(`Node ${node.id} not yet in progress`);\n }\n if (!('endTime' in timing)) {\n throw new Error(`Node ${node.id} not yet completed`);\n }\n return timing;\n }\n}\n\nexport {SimulatorTimingMap};\n"]}
|
|
1
|
+
{"version":3,"file":"SimulationTimingMap.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/simulation/SimulationTimingMap.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\n/**\n * @fileoverview\n *\n * This class encapsulates the type-related validation logic for moving timing information for nodes\n * through the different simulation phases. Methods here ensure that the invariants of simulation hold\n * as nodes are queued, partially simulated, and completed.\n */\n\nimport * as Graph from '../graph/graph.js';\n\ninterface NodeTimingComplete {\n startTime: number;\n endTime: number;\n queuedTime: number;\n estimatedTimeElapsed: number;\n timeElapsed: number;\n timeElapsedOvershoot: number;\n bytesDownloaded: number;\n}\n\ntype NodeTimingQueued = Pick<NodeTimingComplete, 'queuedTime'>;\n\ntype CpuNodeTimingStarted = NodeTimingQueued&Pick<NodeTimingComplete, 'startTime'|'timeElapsed'>;\ntype NetworkNodeTimingStarted = CpuNodeTimingStarted&Pick<NodeTimingComplete, 'timeElapsedOvershoot'|'bytesDownloaded'>;\n\ntype CpuNodeTimingInProgress = CpuNodeTimingStarted&Pick<NodeTimingComplete, 'estimatedTimeElapsed'>;\ntype NetworkNodeTimingInProgress = NetworkNodeTimingStarted&Pick<NodeTimingComplete, 'estimatedTimeElapsed'>;\n\nexport type CpuNodeTimingComplete = CpuNodeTimingInProgress&Pick<NodeTimingComplete, 'endTime'>;\nexport type NetworkNodeTimingComplete =\n NetworkNodeTimingInProgress&Pick<NodeTimingComplete, 'endTime'>&{connectionTiming: ConnectionTiming};\nexport type CompleteNodeTiming = CpuNodeTimingComplete|NetworkNodeTimingComplete;\n\ntype NodeTimingData = NodeTimingQueued|CpuNodeTimingStarted|NetworkNodeTimingStarted|CpuNodeTimingInProgress|\n NetworkNodeTimingInProgress|CpuNodeTimingComplete|NetworkNodeTimingComplete;\n\nexport interface ConnectionTiming {\n dnsResolutionTime?: number;\n connectionTime?: number;\n sslTime?: number;\n timeToFirstByte: number;\n}\n\nclass SimulatorTimingMap {\n _nodeTimings: Map<Graph.Node, NodeTimingData>;\n\n constructor() {\n this._nodeTimings = new Map<Graph.Node, NodeTimingData>();\n }\n\n getNodes(): Graph.Node[] {\n return Array.from(this._nodeTimings.keys());\n }\n\n setReadyToStart(node: Graph.Node, values: {queuedTime: number}): void {\n this._nodeTimings.set(node, values);\n }\n\n setInProgress(node: Graph.Node, values: {startTime: number}): void {\n const nodeTiming = {\n ...this.getQueued(node),\n startTime: values.startTime,\n timeElapsed: 0,\n };\n\n this._nodeTimings.set(\n node,\n node.type === Graph.BaseNode.types.NETWORK ? {...nodeTiming, timeElapsedOvershoot: 0, bytesDownloaded: 0} :\n nodeTiming,\n );\n }\n\n setCompleted(node: Graph.Node, values: {endTime: number, connectionTiming?: ConnectionTiming}): void {\n const nodeTiming = {\n ...this.getInProgress(node),\n endTime: values.endTime,\n connectionTiming: values.connectionTiming,\n };\n\n this._nodeTimings.set(node, nodeTiming);\n }\n\n setCpu(node: Graph.CPUNode, values: {timeElapsed: number}): void {\n const nodeTiming = {\n ...this.getCpuStarted(node),\n timeElapsed: values.timeElapsed,\n };\n\n this._nodeTimings.set(node, nodeTiming);\n }\n\n setCpuEstimated(node: Graph.CPUNode, values: {estimatedTimeElapsed: number}): void {\n const nodeTiming = {\n ...this.getCpuStarted(node),\n estimatedTimeElapsed: values.estimatedTimeElapsed,\n };\n\n this._nodeTimings.set(node, nodeTiming);\n }\n\n setNetwork(\n node: Graph.NetworkNode,\n values: {timeElapsed: number, timeElapsedOvershoot: number, bytesDownloaded: number}): void {\n const nodeTiming = {\n ...this.getNetworkStarted(node),\n timeElapsed: values.timeElapsed,\n timeElapsedOvershoot: values.timeElapsedOvershoot,\n bytesDownloaded: values.bytesDownloaded,\n };\n\n this._nodeTimings.set(node, nodeTiming);\n }\n\n setNetworkEstimated(node: Graph.NetworkNode, values: {estimatedTimeElapsed: number}): void {\n const nodeTiming = {\n ...this.getNetworkStarted(node),\n estimatedTimeElapsed: values.estimatedTimeElapsed,\n };\n\n this._nodeTimings.set(node, nodeTiming);\n }\n\n getQueued(node: Graph.Node): NodeTimingData {\n const timing = this._nodeTimings.get(node);\n if (!timing) {\n throw new Error(`Node ${node.id} not yet queued`);\n }\n return timing;\n }\n\n getCpuStarted(node: Graph.CPUNode): CpuNodeTimingStarted {\n const timing = this._nodeTimings.get(node);\n if (!timing) {\n throw new Error(`Node ${node.id} not yet queued`);\n }\n if (!('startTime' in timing)) {\n throw new Error(`Node ${node.id} not yet started`);\n }\n if ('bytesDownloaded' in timing) {\n throw new Error(`Node ${node.id} timing not valid`);\n }\n return timing;\n }\n\n getNetworkStarted(node: Graph.NetworkNode): NetworkNodeTimingStarted {\n const timing = this._nodeTimings.get(node);\n if (!timing) {\n throw new Error(`Node ${node.id} not yet queued`);\n }\n if (!('startTime' in timing)) {\n throw new Error(`Node ${node.id} not yet started`);\n }\n if (!('bytesDownloaded' in timing)) {\n throw new Error(`Node ${node.id} timing not valid`);\n }\n return timing;\n }\n\n getInProgress(node: Graph.Node): CpuNodeTimingInProgress|NetworkNodeTimingInProgress {\n const timing = this._nodeTimings.get(node);\n if (!timing) {\n throw new Error(`Node ${node.id} not yet queued`);\n }\n if (!('startTime' in timing)) {\n throw new Error(`Node ${node.id} not yet started`);\n }\n if (!('estimatedTimeElapsed' in timing)) {\n throw new Error(`Node ${node.id} not yet in progress`);\n }\n return timing;\n }\n\n getCompleted(node: Graph.Node): CpuNodeTimingComplete|NetworkNodeTimingComplete {\n const timing = this._nodeTimings.get(node);\n if (!timing) {\n throw new Error(`Node ${node.id} not yet queued`);\n }\n if (!('startTime' in timing)) {\n throw new Error(`Node ${node.id} not yet started`);\n }\n if (!('estimatedTimeElapsed' in timing)) {\n throw new Error(`Node ${node.id} not yet in progress`);\n }\n if (!('endTime' in timing)) {\n throw new Error(`Node ${node.id} not yet completed`);\n }\n return timing;\n }\n}\n\nexport {SimulatorTimingMap};\n"]}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import { type NetworkNode } from '../NetworkNode.js';
|
|
4
|
-
import type * as Lantern from '../types/lantern.js';
|
|
1
|
+
import * as Graph from '../graph/graph.js';
|
|
2
|
+
import type * as Lantern from '../types/types.js';
|
|
5
3
|
import { ConnectionPool } from './ConnectionPool.js';
|
|
6
4
|
import { DNSCache } from './DNSCache.js';
|
|
7
5
|
import { type CompleteNodeTiming, type ConnectionTiming, SimulatorTimingMap } from './SimulationTimingMap.js';
|
|
8
6
|
import { TCPConnection } from './TCPConnection.js';
|
|
7
|
+
export interface Result<T = Lantern.AnyNetworkObject> {
|
|
8
|
+
timeInMs: number;
|
|
9
|
+
nodeTimings: Map<Graph.Node<T>, Lantern.Simulation.NodeTiming>;
|
|
10
|
+
}
|
|
9
11
|
declare class Simulator<T = Lantern.AnyNetworkObject> {
|
|
10
12
|
static createSimulator(settings: Lantern.Simulation.Settings): Simulator;
|
|
11
13
|
_options: Required<Lantern.Simulation.Options>;
|
|
@@ -14,26 +16,26 @@ declare class Simulator<T = Lantern.AnyNetworkObject> {
|
|
|
14
16
|
_maximumConcurrentRequests: number;
|
|
15
17
|
_cpuSlowdownMultiplier: number;
|
|
16
18
|
_layoutTaskMultiplier: number;
|
|
17
|
-
_cachedNodeListByStartPosition: Node[];
|
|
19
|
+
_cachedNodeListByStartPosition: Graph.Node[];
|
|
18
20
|
_nodeTimings: SimulatorTimingMap;
|
|
19
21
|
_numberInProgressByType: Map<string, number>;
|
|
20
|
-
_nodes: Record<number, Set<Node>>;
|
|
22
|
+
_nodes: Record<number, Set<Graph.Node>>;
|
|
21
23
|
_dns: DNSCache;
|
|
22
24
|
_connectionPool: ConnectionPool;
|
|
23
25
|
constructor(options?: Lantern.Simulation.Options);
|
|
24
26
|
get rtt(): number;
|
|
25
|
-
_initializeConnectionPool(graph: Node): void;
|
|
27
|
+
_initializeConnectionPool(graph: Graph.Node): void;
|
|
26
28
|
/**
|
|
27
29
|
* Initializes the various state data structures such _nodeTimings and the _node Sets by state.
|
|
28
30
|
*/
|
|
29
31
|
_initializeAuxiliaryData(): void;
|
|
30
32
|
_numberInProgress(type: string): number;
|
|
31
|
-
_markNodeAsReadyToStart(node: Node, queuedTime: number): void;
|
|
32
|
-
_markNodeAsInProgress(node: Node, startTime: number): void;
|
|
33
|
-
_markNodeAsComplete(node: Node, endTime: number, connectionTiming?: ConnectionTiming): void;
|
|
33
|
+
_markNodeAsReadyToStart(node: Graph.Node, queuedTime: number): void;
|
|
34
|
+
_markNodeAsInProgress(node: Graph.Node, startTime: number): void;
|
|
35
|
+
_markNodeAsComplete(node: Graph.Node, endTime: number, connectionTiming?: ConnectionTiming): void;
|
|
34
36
|
_acquireConnection(request: Lantern.NetworkRequest): TCPConnection | null;
|
|
35
|
-
_getNodesSortedByStartPosition(): Node[];
|
|
36
|
-
_startNodeIfPossible(node: Node, totalElapsedTime: number): void;
|
|
37
|
+
_getNodesSortedByStartPosition(): Graph.Node[];
|
|
38
|
+
_startNodeIfPossible(node: Graph.Node, totalElapsedTime: number): void;
|
|
37
39
|
/**
|
|
38
40
|
* Updates each connection in use with the available throughput based on the number of network requests
|
|
39
41
|
* currently in flight.
|
|
@@ -42,9 +44,9 @@ declare class Simulator<T = Lantern.AnyNetworkObject> {
|
|
|
42
44
|
/**
|
|
43
45
|
* Estimates the number of milliseconds remaining given current condidtions before the node is complete.
|
|
44
46
|
*/
|
|
45
|
-
_estimateTimeRemaining(node: Node): number;
|
|
46
|
-
_estimateCPUTimeRemaining(cpuNode: CPUNode): number;
|
|
47
|
-
_estimateNetworkTimeRemaining(networkNode: NetworkNode): number;
|
|
47
|
+
_estimateTimeRemaining(node: Graph.Node): number;
|
|
48
|
+
_estimateCPUTimeRemaining(cpuNode: Graph.CPUNode): number;
|
|
49
|
+
_estimateNetworkTimeRemaining(networkNode: Graph.NetworkNode): number;
|
|
48
50
|
/**
|
|
49
51
|
* Computes and returns the minimum estimated completion time of the nodes currently in progress.
|
|
50
52
|
*/
|
|
@@ -52,10 +54,10 @@ declare class Simulator<T = Lantern.AnyNetworkObject> {
|
|
|
52
54
|
/**
|
|
53
55
|
* Given a time period, computes the progress toward completion that the node made durin that time.
|
|
54
56
|
*/
|
|
55
|
-
_updateProgressMadeInTimePeriod(node: Node, timePeriodLength: number, totalElapsedTime: number): void;
|
|
57
|
+
_updateProgressMadeInTimePeriod(node: Graph.Node, timePeriodLength: number, totalElapsedTime: number): void;
|
|
56
58
|
_computeFinalNodeTimings(): {
|
|
57
|
-
nodeTimings: Map<Node, Lantern.Simulation.NodeTiming>;
|
|
58
|
-
completeNodeTimings: Map<Node, CompleteNodeTiming>;
|
|
59
|
+
nodeTimings: Map<Graph.Node, Lantern.Simulation.NodeTiming>;
|
|
60
|
+
completeNodeTimings: Map<Graph.Node, CompleteNodeTiming>;
|
|
59
61
|
};
|
|
60
62
|
getOptions(): Required<Lantern.Simulation.Options>;
|
|
61
63
|
/**
|
|
@@ -67,16 +69,16 @@ declare class Simulator<T = Lantern.AnyNetworkObject> {
|
|
|
67
69
|
* wait around for a warm connection to be available if the original request was fetched on a warm
|
|
68
70
|
* connection).
|
|
69
71
|
*/
|
|
70
|
-
simulate(graph: Node, options?: {
|
|
72
|
+
simulate(graph: Graph.Node, options?: {
|
|
71
73
|
label?: string;
|
|
72
|
-
}):
|
|
74
|
+
}): Result<T>;
|
|
73
75
|
computeWastedMsFromWastedBytes(wastedBytes: number): number;
|
|
74
|
-
static get allNodeTimings(): Map<string, Map<Node, CompleteNodeTiming>>;
|
|
76
|
+
static get allNodeTimings(): Map<string, Map<Graph.Node, CompleteNodeTiming>>;
|
|
75
77
|
/**
|
|
76
78
|
* We attempt to start nodes by their observed start time using the request priority as a tie breaker.
|
|
77
79
|
* When simulating, just because a low priority image started 5ms before a high priority image doesn't mean
|
|
78
80
|
* it would have happened like that when the network was slower.
|
|
79
81
|
*/
|
|
80
|
-
static _computeNodeStartPosition(node: Node): number;
|
|
82
|
+
static _computeNodeStartPosition(node: Graph.Node): number;
|
|
81
83
|
}
|
|
82
84
|
export { Simulator };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright 2024 The Chromium Authors. All rights reserved.
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
|
-
import
|
|
4
|
+
import * as Graph from '../graph/graph.js';
|
|
5
5
|
import { ConnectionPool } from './ConnectionPool.js';
|
|
6
6
|
import { Constants } from './Constants.js';
|
|
7
7
|
import { DNSCache } from './DNSCache.js';
|
|
@@ -119,7 +119,7 @@ class Simulator {
|
|
|
119
119
|
_initializeConnectionPool(graph) {
|
|
120
120
|
const records = [];
|
|
121
121
|
graph.getRootNode().traverse(node => {
|
|
122
|
-
if (node.type === BaseNode.types.NETWORK) {
|
|
122
|
+
if (node.type === Graph.BaseNode.types.NETWORK) {
|
|
123
123
|
records.push(node.request);
|
|
124
124
|
}
|
|
125
125
|
});
|
|
@@ -184,14 +184,14 @@ class Simulator {
|
|
|
184
184
|
return Array.from(this._cachedNodeListByStartPosition);
|
|
185
185
|
}
|
|
186
186
|
_startNodeIfPossible(node, totalElapsedTime) {
|
|
187
|
-
if (node.type === BaseNode.types.CPU) {
|
|
187
|
+
if (node.type === Graph.BaseNode.types.CPU) {
|
|
188
188
|
// Start a CPU task if there's no other CPU task in process
|
|
189
189
|
if (this._numberInProgress(node.type) === 0) {
|
|
190
190
|
this._markNodeAsInProgress(node, totalElapsedTime);
|
|
191
191
|
}
|
|
192
192
|
return;
|
|
193
193
|
}
|
|
194
|
-
if (node.type !== BaseNode.types.NETWORK) {
|
|
194
|
+
if (node.type !== Graph.BaseNode.types.NETWORK) {
|
|
195
195
|
throw new Error('Unsupported');
|
|
196
196
|
}
|
|
197
197
|
// If a network request is connectionless, we can always start it, so skip the connection checks
|
|
@@ -213,7 +213,7 @@ class Simulator {
|
|
|
213
213
|
* currently in flight.
|
|
214
214
|
*/
|
|
215
215
|
_updateNetworkCapacity() {
|
|
216
|
-
const inFlight = this._numberInProgress(BaseNode.types.NETWORK);
|
|
216
|
+
const inFlight = this._numberInProgress(Graph.BaseNode.types.NETWORK);
|
|
217
217
|
if (inFlight === 0) {
|
|
218
218
|
return;
|
|
219
219
|
}
|
|
@@ -225,10 +225,10 @@ class Simulator {
|
|
|
225
225
|
* Estimates the number of milliseconds remaining given current condidtions before the node is complete.
|
|
226
226
|
*/
|
|
227
227
|
_estimateTimeRemaining(node) {
|
|
228
|
-
if (node.type === BaseNode.types.CPU) {
|
|
228
|
+
if (node.type === Graph.BaseNode.types.CPU) {
|
|
229
229
|
return this._estimateCPUTimeRemaining(node);
|
|
230
230
|
}
|
|
231
|
-
if (node.type === BaseNode.types.NETWORK) {
|
|
231
|
+
if (node.type === Graph.BaseNode.types.NETWORK) {
|
|
232
232
|
return this._estimateNetworkTimeRemaining(node);
|
|
233
233
|
}
|
|
234
234
|
throw new Error('Unsupported');
|
|
@@ -289,7 +289,7 @@ class Simulator {
|
|
|
289
289
|
_updateProgressMadeInTimePeriod(node, timePeriodLength, totalElapsedTime) {
|
|
290
290
|
const timingData = this._nodeTimings.getInProgress(node);
|
|
291
291
|
const isFinished = timingData.estimatedTimeElapsed === timePeriodLength;
|
|
292
|
-
if (node.type === BaseNode.types.CPU || node.isConnectionless) {
|
|
292
|
+
if (node.type === Graph.BaseNode.types.CPU || node.isConnectionless) {
|
|
293
293
|
if (isFinished) {
|
|
294
294
|
this._markNodeAsComplete(node, totalElapsedTime);
|
|
295
295
|
}
|
|
@@ -298,7 +298,7 @@ class Simulator {
|
|
|
298
298
|
}
|
|
299
299
|
return;
|
|
300
300
|
}
|
|
301
|
-
if (node.type !== BaseNode.types.NETWORK) {
|
|
301
|
+
if (node.type !== Graph.BaseNode.types.NETWORK) {
|
|
302
302
|
throw new Error('Unsupported');
|
|
303
303
|
}
|
|
304
304
|
if (!('bytesDownloaded' in timingData)) {
|
|
@@ -363,7 +363,7 @@ class Simulator {
|
|
|
363
363
|
* connection).
|
|
364
364
|
*/
|
|
365
365
|
simulate(graph, options) {
|
|
366
|
-
if (BaseNode.hasCycle(graph)) {
|
|
366
|
+
if (Graph.BaseNode.hasCycle(graph)) {
|
|
367
367
|
throw new Error('Cannot simulate graph with cycle');
|
|
368
368
|
}
|
|
369
369
|
options = Object.assign({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Simulator.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/simulation/Simulator.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {BaseNode, type Node} from '../BaseNode.js';\nimport {type CPUNode} from '../CPUNode.js';\nimport {type NetworkNode} from '../NetworkNode.js';\nimport type * as Lantern from '../types/lantern.js';\n\nimport {ConnectionPool} from './ConnectionPool.js';\nimport {Constants} from './Constants.js';\nimport {DNSCache} from './DNSCache.js';\nimport {type CompleteNodeTiming, type ConnectionTiming, SimulatorTimingMap} from './SimulationTimingMap.js';\nimport {TCPConnection} from './TCPConnection.js';\n\nconst defaultThrottling = Constants.throttling.mobileSlow4G;\n\n// see https://cs.chromium.org/search/?q=kDefaultMaxNumDelayableRequestsPerClient&sq=package:chromium&type=cs\nconst DEFAULT_MAXIMUM_CONCURRENT_REQUESTS = 10;\n// layout tasks tend to be less CPU-bound and do not experience the same increase in duration\nconst DEFAULT_LAYOUT_TASK_MULTIPLIER = 0.5;\n// if a task takes more than 10 seconds it's usually a sign it isn't actually CPU bound and we're overestimating\nconst DEFAULT_MAXIMUM_CPU_TASK_DURATION = 10000;\n\nconst NodeState = {\n NotReadyToStart: 0,\n ReadyToStart: 1,\n InProgress: 2,\n Complete: 3,\n};\n\nconst PriorityStartTimePenalty: Record<Lantern.ResourcePriority, number> = {\n VeryHigh: 0,\n High: 0.25,\n Medium: 0.5,\n Low: 1,\n VeryLow: 2,\n};\n\nconst ALL_SIMULATION_NODE_TIMINGS = new Map<string, Map<Node, CompleteNodeTiming>>();\n\nclass Simulator<T = Lantern.AnyNetworkObject> {\n static createSimulator(settings: Lantern.Simulation.Settings): Simulator {\n const {throttlingMethod, throttling, precomputedLanternData, networkAnalysis} = settings;\n\n const options: Lantern.Simulation.Options = {\n additionalRttByOrigin: networkAnalysis.additionalRttByOrigin,\n serverResponseTimeByOrigin: networkAnalysis.serverResponseTimeByOrigin,\n observedThroughput: networkAnalysis.throughput,\n };\n\n // If we have precomputed lantern data, overwrite our observed estimates and use precomputed instead\n // for increased stability.\n if (precomputedLanternData) {\n options.additionalRttByOrigin = new Map(Object.entries(precomputedLanternData.additionalRttByOrigin));\n options.serverResponseTimeByOrigin = new Map(Object.entries(precomputedLanternData.serverResponseTimeByOrigin));\n }\n\n switch (throttlingMethod) {\n case 'provided':\n options.rtt = networkAnalysis.rtt;\n options.throughput = networkAnalysis.throughput;\n options.cpuSlowdownMultiplier = 1;\n options.layoutTaskMultiplier = 1;\n break;\n case 'devtools':\n if (throttling) {\n options.rtt = throttling.requestLatencyMs / Constants.throttling.DEVTOOLS_RTT_ADJUSTMENT_FACTOR;\n options.throughput =\n throttling.downloadThroughputKbps * 1024 / Constants.throttling.DEVTOOLS_THROUGHPUT_ADJUSTMENT_FACTOR;\n }\n\n options.cpuSlowdownMultiplier = 1;\n options.layoutTaskMultiplier = 1;\n break;\n case 'simulate':\n if (throttling) {\n options.rtt = throttling.rttMs;\n options.throughput = throttling.throughputKbps * 1024;\n options.cpuSlowdownMultiplier = throttling.cpuSlowdownMultiplier;\n }\n break;\n default:\n // intentionally fallback to simulator defaults\n break;\n }\n\n return new Simulator(options);\n }\n\n _options: Required<Lantern.Simulation.Options>;\n _rtt: number;\n _throughput: number;\n _maximumConcurrentRequests: number;\n _cpuSlowdownMultiplier: number;\n _layoutTaskMultiplier: number;\n _cachedNodeListByStartPosition: Node[];\n _nodeTimings: SimulatorTimingMap;\n _numberInProgressByType: Map<string, number>;\n _nodes: Record<number, Set<Node>>;\n _dns: DNSCache;\n _connectionPool: ConnectionPool;\n\n constructor(options?: Lantern.Simulation.Options) {\n this._options = Object.assign(\n {\n rtt: defaultThrottling.rttMs,\n throughput: defaultThrottling.throughputKbps * 1024,\n maximumConcurrentRequests: DEFAULT_MAXIMUM_CONCURRENT_REQUESTS,\n cpuSlowdownMultiplier: defaultThrottling.cpuSlowdownMultiplier,\n layoutTaskMultiplier: DEFAULT_LAYOUT_TASK_MULTIPLIER,\n additionalRttByOrigin: new Map(),\n serverResponseTimeByOrigin: new Map(),\n },\n options,\n );\n\n this._rtt = this._options.rtt;\n this._throughput = this._options.throughput;\n this._maximumConcurrentRequests = Math.max(\n Math.min(\n TCPConnection.maximumSaturatedConnections(this._rtt, this._throughput),\n this._options.maximumConcurrentRequests,\n ),\n 1);\n this._cpuSlowdownMultiplier = this._options.cpuSlowdownMultiplier;\n this._layoutTaskMultiplier = this._cpuSlowdownMultiplier * this._options.layoutTaskMultiplier;\n this._cachedNodeListByStartPosition = [];\n\n // Properties reset on every `.simulate` call but duplicated here for type checking\n this._nodeTimings = new SimulatorTimingMap();\n this._numberInProgressByType = new Map<string, number>();\n this._nodes = {};\n this._dns = new DNSCache({rtt: this._rtt});\n // @ts-expect-error\n this._connectionPool = null;\n\n if (!Number.isFinite(this._rtt)) {\n throw new Error(`Invalid rtt ${this._rtt}`);\n }\n if (!Number.isFinite(this._throughput)) {\n throw new Error(`Invalid rtt ${this._throughput}`);\n }\n }\n\n get rtt(): number {\n return this._rtt;\n }\n\n _initializeConnectionPool(graph: Node): void {\n const records: Lantern.NetworkRequest[] = [];\n graph.getRootNode().traverse(node => {\n if (node.type === BaseNode.types.NETWORK) {\n records.push(node.request);\n }\n });\n\n this._connectionPool = new ConnectionPool(records, this._options);\n }\n\n /**\n * Initializes the various state data structures such _nodeTimings and the _node Sets by state.\n */\n _initializeAuxiliaryData(): void {\n this._nodeTimings = new SimulatorTimingMap();\n this._numberInProgressByType = new Map();\n\n this._nodes = {};\n this._cachedNodeListByStartPosition = [];\n // NOTE: We don't actually need *all* of these sets, but the clarity that each node progresses\n // through the system is quite nice.\n for (const state of Object.values(NodeState)) {\n this._nodes[state] = new Set();\n }\n }\n\n _numberInProgress(type: string): number {\n return this._numberInProgressByType.get(type) || 0;\n }\n\n _markNodeAsReadyToStart(node: Node, queuedTime: number): void {\n const nodeStartPosition = Simulator._computeNodeStartPosition(node);\n const firstNodeIndexWithGreaterStartPosition = this._cachedNodeListByStartPosition.findIndex(\n candidate => Simulator._computeNodeStartPosition(candidate) > nodeStartPosition);\n const insertionIndex = firstNodeIndexWithGreaterStartPosition === -1 ? this._cachedNodeListByStartPosition.length :\n firstNodeIndexWithGreaterStartPosition;\n this._cachedNodeListByStartPosition.splice(insertionIndex, 0, node);\n\n this._nodes[NodeState.ReadyToStart].add(node);\n this._nodes[NodeState.NotReadyToStart].delete(node);\n this._nodeTimings.setReadyToStart(node, {queuedTime});\n }\n\n _markNodeAsInProgress(node: Node, startTime: number): void {\n const indexOfNodeToStart = this._cachedNodeListByStartPosition.indexOf(node);\n this._cachedNodeListByStartPosition.splice(indexOfNodeToStart, 1);\n\n this._nodes[NodeState.InProgress].add(node);\n this._nodes[NodeState.ReadyToStart].delete(node);\n this._numberInProgressByType.set(node.type, this._numberInProgress(node.type) + 1);\n this._nodeTimings.setInProgress(node, {startTime});\n }\n\n _markNodeAsComplete(node: Node, endTime: number, connectionTiming?: ConnectionTiming): void {\n this._nodes[NodeState.Complete].add(node);\n this._nodes[NodeState.InProgress].delete(node);\n this._numberInProgressByType.set(node.type, this._numberInProgress(node.type) - 1);\n this._nodeTimings.setCompleted(node, {endTime, connectionTiming});\n\n // Try to add all its dependents to the queue\n for (const dependent of node.getDependents()) {\n // Skip dependent node if one of its dependencies hasn't finished yet\n const dependencies = dependent.getDependencies();\n if (dependencies.some(dep => !this._nodes[NodeState.Complete].has(dep))) {\n continue;\n }\n\n // Otherwise add it to the queue\n this._markNodeAsReadyToStart(dependent, endTime);\n }\n }\n\n _acquireConnection(request: Lantern.NetworkRequest): TCPConnection|null {\n return this._connectionPool.acquire(request);\n }\n\n _getNodesSortedByStartPosition(): Node[] {\n // Make a copy so we don't skip nodes due to concurrent modification\n return Array.from(this._cachedNodeListByStartPosition);\n }\n\n _startNodeIfPossible(node: Node, totalElapsedTime: number): void {\n if (node.type === BaseNode.types.CPU) {\n // Start a CPU task if there's no other CPU task in process\n if (this._numberInProgress(node.type) === 0) {\n this._markNodeAsInProgress(node, totalElapsedTime);\n }\n\n return;\n }\n\n if (node.type !== BaseNode.types.NETWORK) {\n throw new Error('Unsupported');\n }\n\n // If a network request is connectionless, we can always start it, so skip the connection checks\n if (!node.isConnectionless) {\n // Start a network request if we're not at max requests and a connection is available\n const numberOfActiveRequests = this._numberInProgress(node.type);\n if (numberOfActiveRequests >= this._maximumConcurrentRequests) {\n return;\n }\n const connection = this._acquireConnection(node.request);\n if (!connection) {\n return;\n }\n }\n\n this._markNodeAsInProgress(node, totalElapsedTime);\n }\n\n /**\n * Updates each connection in use with the available throughput based on the number of network requests\n * currently in flight.\n */\n _updateNetworkCapacity(): void {\n const inFlight = this._numberInProgress(BaseNode.types.NETWORK);\n if (inFlight === 0) {\n return;\n }\n\n for (const connection of this._connectionPool.connectionsInUse()) {\n connection.setThroughput(this._throughput / inFlight);\n }\n }\n\n /**\n * Estimates the number of milliseconds remaining given current condidtions before the node is complete.\n */\n _estimateTimeRemaining(node: Node): number {\n if (node.type === BaseNode.types.CPU) {\n return this._estimateCPUTimeRemaining(node);\n }\n if (node.type === BaseNode.types.NETWORK) {\n return this._estimateNetworkTimeRemaining(node);\n }\n throw new Error('Unsupported');\n }\n\n _estimateCPUTimeRemaining(cpuNode: CPUNode): number {\n const timingData = this._nodeTimings.getCpuStarted(cpuNode);\n const multiplier = cpuNode.didPerformLayout() ? this._layoutTaskMultiplier : this._cpuSlowdownMultiplier;\n const totalDuration = Math.min(\n Math.round(cpuNode.duration / 1000 * multiplier),\n DEFAULT_MAXIMUM_CPU_TASK_DURATION,\n );\n const estimatedTimeElapsed = totalDuration - timingData.timeElapsed;\n this._nodeTimings.setCpuEstimated(cpuNode, {estimatedTimeElapsed});\n return estimatedTimeElapsed;\n }\n\n _estimateNetworkTimeRemaining(networkNode: NetworkNode): number {\n const request = networkNode.request;\n const timingData = this._nodeTimings.getNetworkStarted(networkNode);\n\n let timeElapsed = 0;\n if (networkNode.fromDiskCache) {\n // Rough access time for seeking to location on disk and reading sequentially.\n // 8ms per seek + 20ms/MB\n // @see http://norvig.com/21-days.html#answers\n const sizeInMb = (request.resourceSize || 0) / 1024 / 1024;\n timeElapsed = 8 + 20 * sizeInMb - timingData.timeElapsed;\n } else if (networkNode.isNonNetworkProtocol) {\n // Estimates for the overhead of a data URL in Chromium and the decoding time for base64-encoded data.\n // 2ms per request + 10ms/MB\n // @see traces on https://dopiaza.org/tools/datauri/examples/index.php\n const sizeInMb = (request.resourceSize || 0) / 1024 / 1024;\n timeElapsed = 2 + 10 * sizeInMb - timingData.timeElapsed;\n } else {\n const connection = this._connectionPool.acquireActiveConnectionFromRequest(request);\n const dnsResolutionTime = this._dns.getTimeUntilResolution(request, {\n requestedAt: timingData.startTime,\n shouldUpdateCache: true,\n });\n const timeAlreadyElapsed = timingData.timeElapsed;\n const calculation = connection.simulateDownloadUntil(\n request.transferSize - timingData.bytesDownloaded,\n {timeAlreadyElapsed, dnsResolutionTime, maximumTimeToElapse: Infinity},\n );\n\n timeElapsed = calculation.timeElapsed;\n }\n\n const estimatedTimeElapsed = timeElapsed + timingData.timeElapsedOvershoot;\n this._nodeTimings.setNetworkEstimated(networkNode, {estimatedTimeElapsed});\n return estimatedTimeElapsed;\n }\n\n /**\n * Computes and returns the minimum estimated completion time of the nodes currently in progress.\n */\n _findNextNodeCompletionTime(): number {\n let minimumTime = Infinity;\n for (const node of this._nodes[NodeState.InProgress]) {\n minimumTime = Math.min(minimumTime, this._estimateTimeRemaining(node));\n }\n\n return minimumTime;\n }\n\n /**\n * Given a time period, computes the progress toward completion that the node made durin that time.\n */\n _updateProgressMadeInTimePeriod(node: Node, timePeriodLength: number, totalElapsedTime: number): void {\n const timingData = this._nodeTimings.getInProgress(node);\n const isFinished = timingData.estimatedTimeElapsed === timePeriodLength;\n\n if (node.type === BaseNode.types.CPU || node.isConnectionless) {\n if (isFinished) {\n this._markNodeAsComplete(node, totalElapsedTime);\n } else {\n timingData.timeElapsed += timePeriodLength;\n }\n return;\n }\n\n if (node.type !== BaseNode.types.NETWORK) {\n throw new Error('Unsupported');\n }\n if (!('bytesDownloaded' in timingData)) {\n throw new Error('Invalid timing data');\n }\n\n const request = node.request;\n const connection = this._connectionPool.acquireActiveConnectionFromRequest(request);\n const dnsResolutionTime = this._dns.getTimeUntilResolution(request, {\n requestedAt: timingData.startTime,\n shouldUpdateCache: true,\n });\n const calculation = connection.simulateDownloadUntil(\n request.transferSize - timingData.bytesDownloaded,\n {\n dnsResolutionTime,\n timeAlreadyElapsed: timingData.timeElapsed,\n maximumTimeToElapse: timePeriodLength - timingData.timeElapsedOvershoot,\n },\n );\n\n connection.setCongestionWindow(calculation.congestionWindow);\n connection.setH2OverflowBytesDownloaded(calculation.extraBytesDownloaded);\n\n if (isFinished) {\n connection.setWarmed(true);\n this._connectionPool.release(request);\n this._markNodeAsComplete(node, totalElapsedTime, calculation.connectionTiming);\n } else {\n timingData.timeElapsed += calculation.timeElapsed;\n timingData.timeElapsedOvershoot += calculation.timeElapsed - timePeriodLength;\n timingData.bytesDownloaded += calculation.bytesDownloaded;\n }\n }\n\n _computeFinalNodeTimings():\n {nodeTimings: Map<Node, Lantern.Simulation.NodeTiming>, completeNodeTimings: Map<Node, CompleteNodeTiming>} {\n const completeNodeTimingEntries: Array<[Node, CompleteNodeTiming]> = this._nodeTimings.getNodes().map(node => {\n return [node, this._nodeTimings.getCompleted(node)];\n });\n\n // Most consumers will want the entries sorted by startTime, so insert them in that order\n completeNodeTimingEntries.sort((a, b) => a[1].startTime - b[1].startTime);\n\n // Trimmed version of type `Lantern.Simulation.NodeTiming`.\n const nodeTimingEntries: Array<[Node, Lantern.Simulation.NodeTiming]> =\n completeNodeTimingEntries.map(([node, timing]) => {\n return [\n node,\n {\n startTime: timing.startTime,\n endTime: timing.endTime,\n duration: timing.endTime - timing.startTime,\n },\n ];\n });\n\n return {\n nodeTimings: new Map(nodeTimingEntries),\n completeNodeTimings: new Map(completeNodeTimingEntries),\n };\n }\n\n getOptions(): Required<Lantern.Simulation.Options> {\n return this._options;\n }\n\n /**\n * Estimates the time taken to process all of the graph's nodes, returns the overall time along with\n * each node annotated by start/end times.\n *\n * Simulator/connection pool are allowed to deviate from what was\n * observed in the trace/devtoolsLog and start requests as soon as they are queued (i.e. do not\n * wait around for a warm connection to be available if the original request was fetched on a warm\n * connection).\n */\n simulate(graph: Node, options?: {label?: string}): Lantern.Simulation.Result<T> {\n if (BaseNode.hasCycle(graph)) {\n throw new Error('Cannot simulate graph with cycle');\n }\n\n options = Object.assign(\n {\n label: undefined,\n },\n options);\n\n // initialize the necessary data containers\n this._dns = new DNSCache({rtt: this._rtt});\n this._initializeConnectionPool(graph);\n this._initializeAuxiliaryData();\n\n const nodesNotReadyToStart = this._nodes[NodeState.NotReadyToStart];\n const nodesReadyToStart = this._nodes[NodeState.ReadyToStart];\n const nodesInProgress = this._nodes[NodeState.InProgress];\n\n const rootNode = graph.getRootNode();\n rootNode.traverse(node => nodesNotReadyToStart.add(node));\n let totalElapsedTime = 0;\n let iteration = 0;\n\n // root node is always ready to start\n this._markNodeAsReadyToStart(rootNode, totalElapsedTime);\n\n // loop as long as we have nodes in the queue or currently in progress\n while (nodesReadyToStart.size || nodesInProgress.size) {\n // move all possible queued nodes to in progress\n for (const node of this._getNodesSortedByStartPosition()) {\n this._startNodeIfPossible(node, totalElapsedTime);\n }\n\n if (!nodesInProgress.size) {\n // Interplay between fromDiskCache and connectionReused can be incorrect,\n // have to give up.\n throw new Error('Failed to start a node');\n }\n\n // set the available throughput for all connections based on # inflight\n this._updateNetworkCapacity();\n\n // find the time that the next node will finish\n const minimumTime = this._findNextNodeCompletionTime();\n totalElapsedTime += minimumTime;\n\n // While this is no longer strictly necessary, it's always better than hanging\n if (!Number.isFinite(minimumTime) || iteration > 100000) {\n throw new Error('Simulation failed, depth exceeded');\n }\n\n iteration++;\n // update how far each node will progress until that point\n for (const node of nodesInProgress) {\n this._updateProgressMadeInTimePeriod(node, minimumTime, totalElapsedTime);\n }\n }\n\n // `nodeTimings` are used for simulator consumers, `completeNodeTimings` kept for debugging.\n const {nodeTimings, completeNodeTimings} = this._computeFinalNodeTimings();\n ALL_SIMULATION_NODE_TIMINGS.set(options.label || 'unlabeled', completeNodeTimings);\n\n return {\n timeInMs: totalElapsedTime,\n nodeTimings,\n };\n }\n\n computeWastedMsFromWastedBytes(wastedBytes: number): number {\n const {throughput, observedThroughput} = this._options;\n\n // https://github.com/GoogleChrome/lighthouse/pull/13323#issuecomment-962031709\n // 0 throughput means the no (additional) throttling is expected.\n // This is common for desktop + devtools throttling where throttling is additive and we don't want any additional.\n const bitsPerSecond = throughput === 0 ? observedThroughput : throughput;\n if (bitsPerSecond === 0) {\n return 0;\n }\n\n const wastedBits = wastedBytes * 8;\n const wastedMs = wastedBits / bitsPerSecond * 1000;\n\n // This is an estimate of wasted time, so we won't be more precise than 10ms.\n return Math.round(wastedMs / 10) * 10;\n }\n\n static get allNodeTimings(): Map<string, Map<Node, CompleteNodeTiming>> {\n return ALL_SIMULATION_NODE_TIMINGS;\n }\n\n /**\n * We attempt to start nodes by their observed start time using the request priority as a tie breaker.\n * When simulating, just because a low priority image started 5ms before a high priority image doesn't mean\n * it would have happened like that when the network was slower.\n */\n static _computeNodeStartPosition(node: Node): number {\n if (node.type === 'cpu') {\n return node.startTime;\n }\n return node.startTime + (PriorityStartTimePenalty[node.request.priority] * 1000 * 1000 || 0);\n }\n}\n\nexport {Simulator};\n"]}
|
|
1
|
+
{"version":3,"file":"Simulator.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/simulation/Simulator.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAG3C,OAAO,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AACvC,OAAO,EAAiD,kBAAkB,EAAC,MAAM,0BAA0B,CAAC;AAC5G,OAAO,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AAOjD,MAAM,iBAAiB,GAAG,SAAS,CAAC,UAAU,CAAC,YAAY,CAAC;AAE5D,6GAA6G;AAC7G,MAAM,mCAAmC,GAAG,EAAE,CAAC;AAC/C,6FAA6F;AAC7F,MAAM,8BAA8B,GAAG,GAAG,CAAC;AAC3C,gHAAgH;AAChH,MAAM,iCAAiC,GAAG,KAAK,CAAC;AAEhD,MAAM,SAAS,GAAG;IAChB,eAAe,EAAE,CAAC;IAClB,YAAY,EAAE,CAAC;IACf,UAAU,EAAE,CAAC;IACb,QAAQ,EAAE,CAAC;CACZ,CAAC;AAEF,MAAM,wBAAwB,GAA6C;IACzE,QAAQ,EAAE,CAAC;IACX,IAAI,EAAE,IAAI;IACV,MAAM,EAAE,GAAG;IACX,GAAG,EAAE,CAAC;IACN,OAAO,EAAE,CAAC;CACX,CAAC;AAEF,MAAM,2BAA2B,GAAG,IAAI,GAAG,EAA+C,CAAC;AAE3F,MAAM,SAAS;IACb,MAAM,CAAC,eAAe,CAAC,QAAqC;QAC1D,MAAM,EAAC,gBAAgB,EAAE,UAAU,EAAE,sBAAsB,EAAE,eAAe,EAAC,GAAG,QAAQ,CAAC;QAEzF,MAAM,OAAO,GAA+B;YAC1C,qBAAqB,EAAE,eAAe,CAAC,qBAAqB;YAC5D,0BAA0B,EAAE,eAAe,CAAC,0BAA0B;YACtE,kBAAkB,EAAE,eAAe,CAAC,UAAU;SAC/C,CAAC;QAEF,oGAAoG;QACpG,2BAA2B;QAC3B,IAAI,sBAAsB,EAAE,CAAC;YAC3B,OAAO,CAAC,qBAAqB,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,sBAAsB,CAAC,qBAAqB,CAAC,CAAC,CAAC;YACtG,OAAO,CAAC,0BAA0B,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,sBAAsB,CAAC,0BAA0B,CAAC,CAAC,CAAC;QAClH,CAAC;QAED,QAAQ,gBAAgB,EAAE,CAAC;YACzB,KAAK,UAAU;gBACb,OAAO,CAAC,GAAG,GAAG,eAAe,CAAC,GAAG,CAAC;gBAClC,OAAO,CAAC,UAAU,GAAG,eAAe,CAAC,UAAU,CAAC;gBAChD,OAAO,CAAC,qBAAqB,GAAG,CAAC,CAAC;gBAClC,OAAO,CAAC,oBAAoB,GAAG,CAAC,CAAC;gBACjC,MAAM;YACR,KAAK,UAAU;gBACb,IAAI,UAAU,EAAE,CAAC;oBACf,OAAO,CAAC,GAAG,GAAG,UAAU,CAAC,gBAAgB,GAAG,SAAS,CAAC,UAAU,CAAC,8BAA8B,CAAC;oBAChG,OAAO,CAAC,UAAU;wBACd,UAAU,CAAC,sBAAsB,GAAG,IAAI,GAAG,SAAS,CAAC,UAAU,CAAC,qCAAqC,CAAC;gBAC5G,CAAC;gBAED,OAAO,CAAC,qBAAqB,GAAG,CAAC,CAAC;gBAClC,OAAO,CAAC,oBAAoB,GAAG,CAAC,CAAC;gBACjC,MAAM;YACR,KAAK,UAAU;gBACb,IAAI,UAAU,EAAE,CAAC;oBACf,OAAO,CAAC,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC;oBAC/B,OAAO,CAAC,UAAU,GAAG,UAAU,CAAC,cAAc,GAAG,IAAI,CAAC;oBACtD,OAAO,CAAC,qBAAqB,GAAG,UAAU,CAAC,qBAAqB,CAAC;gBACnE,CAAC;gBACD,MAAM;YACR;gBACE,+CAA+C;gBAC/C,MAAM;QACV,CAAC;QAED,OAAO,IAAI,SAAS,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAED,QAAQ,CAAuC;IAC/C,IAAI,CAAS;IACb,WAAW,CAAS;IACpB,0BAA0B,CAAS;IACnC,sBAAsB,CAAS;IAC/B,qBAAqB,CAAS;IAC9B,8BAA8B,CAAe;IAC7C,YAAY,CAAqB;IACjC,uBAAuB,CAAsB;IAC7C,MAAM,CAAkC;IACxC,IAAI,CAAW;IACf,eAAe,CAAiB;IAEhC,YAAY,OAAoC;QAC9C,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,CACzB;YACE,GAAG,EAAE,iBAAiB,CAAC,KAAK;YAC5B,UAAU,EAAE,iBAAiB,CAAC,cAAc,GAAG,IAAI;YACnD,yBAAyB,EAAE,mCAAmC;YAC9D,qBAAqB,EAAE,iBAAiB,CAAC,qBAAqB;YAC9D,oBAAoB,EAAE,8BAA8B;YACpD,qBAAqB,EAAE,IAAI,GAAG,EAAE;YAChC,0BAA0B,EAAE,IAAI,GAAG,EAAE;SACtC,EACD,OAAO,CACV,CAAC;QAEF,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAC9B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC5C,IAAI,CAAC,0BAA0B,GAAG,IAAI,CAAC,GAAG,CACtC,IAAI,CAAC,GAAG,CACJ,aAAa,CAAC,2BAA2B,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,EACtE,IAAI,CAAC,QAAQ,CAAC,yBAAyB,CACtC,EACL,CAAC,CAAC,CAAC;QACP,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC,QAAQ,CAAC,qBAAqB,CAAC;QAClE,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC;QAC9F,IAAI,CAAC,8BAA8B,GAAG,EAAE,CAAC;QAEzC,mFAAmF;QACnF,IAAI,CAAC,YAAY,GAAG,IAAI,kBAAkB,EAAE,CAAC;QAC7C,IAAI,CAAC,uBAAuB,GAAG,IAAI,GAAG,EAAkB,CAAC;QACzD,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,IAAI,QAAQ,CAAC,EAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAC,CAAC,CAAC;QAC3C,mBAAmB;QACnB,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAE5B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9C,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAED,IAAI,GAAG;QACL,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,yBAAyB,CAAC,KAAiB;QACzC,MAAM,OAAO,GAA6B,EAAE,CAAC;QAC7C,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;YAClC,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;gBAC/C,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,eAAe,GAAG,IAAI,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpE,CAAC;IAED;;OAEG;IACH,wBAAwB;QACtB,IAAI,CAAC,YAAY,GAAG,IAAI,kBAAkB,EAAE,CAAC;QAC7C,IAAI,CAAC,uBAAuB,GAAG,IAAI,GAAG,EAAE,CAAC;QAEzC,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,8BAA8B,GAAG,EAAE,CAAC;QACzC,8FAA8F;QAC9F,oCAAoC;QACpC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;QACjC,CAAC;IACH,CAAC;IAED,iBAAiB,CAAC,IAAY;QAC5B,OAAO,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrD,CAAC;IAED,uBAAuB,CAAC,IAAgB,EAAE,UAAkB;QAC1D,MAAM,iBAAiB,GAAG,SAAS,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC;QACpE,MAAM,sCAAsC,GAAG,IAAI,CAAC,8BAA8B,CAAC,SAAS,CACxF,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,yBAAyB,CAAC,SAAS,CAAC,GAAG,iBAAiB,CAAC,CAAC;QACrF,MAAM,cAAc,GAAG,sCAAsC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,8BAA8B,CAAC,MAAM,CAAC,CAAC;YAC5C,sCAAsC,CAAC;QAC9G,IAAI,CAAC,8BAA8B,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;QAEpE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACpD,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,IAAI,EAAE,EAAC,UAAU,EAAC,CAAC,CAAC;IACxD,CAAC;IAED,qBAAqB,CAAC,IAAgB,EAAE,SAAiB;QACvD,MAAM,kBAAkB,GAAG,IAAI,CAAC,8BAA8B,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7E,IAAI,CAAC,8BAA8B,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;QAElE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACnF,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,IAAI,EAAE,EAAC,SAAS,EAAC,CAAC,CAAC;IACrD,CAAC;IAED,mBAAmB,CAAC,IAAgB,EAAE,OAAe,EAAE,gBAAmC;QACxF,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACnF,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,IAAI,EAAE,EAAC,OAAO,EAAE,gBAAgB,EAAC,CAAC,CAAC;QAElE,6CAA6C;QAC7C,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC;YAC7C,qEAAqE;YACrE,MAAM,YAAY,GAAG,SAAS,CAAC,eAAe,EAAE,CAAC;YACjD,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;gBACxE,SAAS;YACX,CAAC;YAED,gCAAgC;YAChC,IAAI,CAAC,uBAAuB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAED,kBAAkB,CAAC,OAA+B;QAChD,OAAO,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,CAAC;IAED,8BAA8B;QAC5B,oEAAoE;QACpE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;IACzD,CAAC;IAED,oBAAoB,CAAC,IAAgB,EAAE,gBAAwB;QAC7D,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;YAC3C,2DAA2D;YAC3D,IAAI,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC5C,IAAI,CAAC,qBAAqB,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;YACrD,CAAC;YAED,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YAC/C,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;QACjC,CAAC;QAED,gGAAgG;QAChG,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,qFAAqF;YACrF,MAAM,sBAAsB,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjE,IAAI,sBAAsB,IAAI,IAAI,CAAC,0BAA0B,EAAE,CAAC;gBAC9D,OAAO;YACT,CAAC;YACD,MAAM,UAAU,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACzD,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,OAAO;YACT,CAAC;QACH,CAAC;QAED,IAAI,CAAC,qBAAqB,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;IACrD,CAAC;IAED;;;OAGG;IACH,sBAAsB;QACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACtE,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;YACnB,OAAO;QACT,CAAC;QAED,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,eAAe,CAAC,gBAAgB,EAAE,EAAE,CAAC;YACjE,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,GAAG,QAAQ,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAED;;OAEG;IACH,sBAAsB,CAAC,IAAgB;QACrC,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;YAC3C,OAAO,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC;QAC9C,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YAC/C,OAAO,IAAI,CAAC,6BAA6B,CAAC,IAAI,CAAC,CAAC;QAClD,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;IACjC,CAAC;IAED,yBAAyB,CAAC,OAAsB;QAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC5D,MAAM,UAAU,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC;QACzG,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAC1B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,GAAG,IAAI,GAAG,UAAU,CAAC,EAChD,iCAAiC,CACpC,CAAC;QACF,MAAM,oBAAoB,GAAG,aAAa,GAAG,UAAU,CAAC,WAAW,CAAC;QACpE,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,OAAO,EAAE,EAAC,oBAAoB,EAAC,CAAC,CAAC;QACnE,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IAED,6BAA6B,CAAC,WAA8B;QAC1D,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC;QACpC,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;QAEpE,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,IAAI,WAAW,CAAC,aAAa,EAAE,CAAC;YAC9B,8EAA8E;YAC9E,yBAAyB;YACzB,8CAA8C;YAC9C,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;YAC3D,WAAW,GAAG,CAAC,GAAG,EAAE,GAAG,QAAQ,GAAG,UAAU,CAAC,WAAW,CAAC;QAC3D,CAAC;aAAM,IAAI,WAAW,CAAC,oBAAoB,EAAE,CAAC;YAC5C,sGAAsG;YACtG,4BAA4B;YAC5B,sEAAsE;YACtE,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;YAC3D,WAAW,GAAG,CAAC,GAAG,EAAE,GAAG,QAAQ,GAAG,UAAU,CAAC,WAAW,CAAC;QAC3D,CAAC;aAAM,CAAC;YACN,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,kCAAkC,CAAC,OAAO,CAAC,CAAC;YACpF,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,sBAAsB,CAAC,OAAO,EAAE;gBAClE,WAAW,EAAE,UAAU,CAAC,SAAS;gBACjC,iBAAiB,EAAE,IAAI;aACxB,CAAC,CAAC;YACH,MAAM,kBAAkB,GAAG,UAAU,CAAC,WAAW,CAAC;YAClD,MAAM,WAAW,GAAG,UAAU,CAAC,qBAAqB,CAChD,OAAO,CAAC,YAAY,GAAG,UAAU,CAAC,eAAe,EACjD,EAAC,kBAAkB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,QAAQ,EAAC,CACzE,CAAC;YAEF,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC;QACxC,CAAC;QAED,MAAM,oBAAoB,GAAG,WAAW,GAAG,UAAU,CAAC,oBAAoB,CAAC;QAC3E,IAAI,CAAC,YAAY,CAAC,mBAAmB,CAAC,WAAW,EAAE,EAAC,oBAAoB,EAAC,CAAC,CAAC;QAC3E,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IAED;;OAEG;IACH,2BAA2B;QACzB,IAAI,WAAW,GAAG,QAAQ,CAAC;QAC3B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC;YACrD,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC,CAAC;QACzE,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,+BAA+B,CAAC,IAAgB,EAAE,gBAAwB,EAAE,gBAAwB;QAClG,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QACzD,MAAM,UAAU,GAAG,UAAU,CAAC,oBAAoB,KAAK,gBAAgB,CAAC;QAExE,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACpE,IAAI,UAAU,EAAE,CAAC;gBACf,IAAI,CAAC,mBAAmB,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;YACnD,CAAC;iBAAM,CAAC;gBACN,UAAU,CAAC,WAAW,IAAI,gBAAgB,CAAC;YAC7C,CAAC;YACD,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YAC/C,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;QACjC,CAAC;QACD,IAAI,CAAC,CAAC,iBAAiB,IAAI,UAAU,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACzC,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7B,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,kCAAkC,CAAC,OAAO,CAAC,CAAC;QACpF,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,sBAAsB,CAAC,OAAO,EAAE;YAClE,WAAW,EAAE,UAAU,CAAC,SAAS;YACjC,iBAAiB,EAAE,IAAI;SACxB,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,UAAU,CAAC,qBAAqB,CAChD,OAAO,CAAC,YAAY,GAAG,UAAU,CAAC,eAAe,EACjD;YACE,iBAAiB;YACjB,kBAAkB,EAAE,UAAU,CAAC,WAAW;YAC1C,mBAAmB,EAAE,gBAAgB,GAAG,UAAU,CAAC,oBAAoB;SACxE,CACJ,CAAC;QAEF,UAAU,CAAC,mBAAmB,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC;QAC7D,UAAU,CAAC,4BAA4B,CAAC,WAAW,CAAC,oBAAoB,CAAC,CAAC;QAE1E,IAAI,UAAU,EAAE,CAAC;YACf,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACtC,IAAI,CAAC,mBAAmB,CAAC,IAAI,EAAE,gBAAgB,EAAE,WAAW,CAAC,gBAAgB,CAAC,CAAC;QACjF,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,WAAW,IAAI,WAAW,CAAC,WAAW,CAAC;YAClD,UAAU,CAAC,oBAAoB,IAAI,WAAW,CAAC,WAAW,GAAG,gBAAgB,CAAC;YAC9E,UAAU,CAAC,eAAe,IAAI,WAAW,CAAC,eAAe,CAAC;QAC5D,CAAC;IACH,CAAC;IAED,wBAAwB;QAItB,MAAM,yBAAyB,GAC3B,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YACtC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;QAEP,yFAAyF;QACzF,yBAAyB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAE1E,2DAA2D;QAC3D,MAAM,iBAAiB,GACnB,yBAAyB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE;YAC/C,OAAO;gBACL,IAAI;gBACJ;oBACE,SAAS,EAAE,MAAM,CAAC,SAAS;oBAC3B,OAAO,EAAE,MAAM,CAAC,OAAO;oBACvB,QAAQ,EAAE,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,SAAS;iBAC5C;aACF,CAAC;QACJ,CAAC,CAAC,CAAC;QAEP,OAAO;YACL,WAAW,EAAE,IAAI,GAAG,CAAC,iBAAiB,CAAC;YACvC,mBAAmB,EAAE,IAAI,GAAG,CAAC,yBAAyB,CAAC;SACxD,CAAC;IACJ,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED;;;;;;;;OAQG;IACH,QAAQ,CAAC,KAAiB,EAAE,OAA0B;QACpD,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACtD,CAAC;QAED,OAAO,GAAG,MAAM,CAAC,MAAM,CACnB;YACE,KAAK,EAAE,SAAS;SACjB,EACD,OAAO,CAAC,CAAC;QAEb,2CAA2C;QAC3C,IAAI,CAAC,IAAI,GAAG,IAAI,QAAQ,CAAC,EAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAC,CAAC,CAAC;QAC3C,IAAI,CAAC,yBAAyB,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,CAAC,wBAAwB,EAAE,CAAC;QAEhC,MAAM,oBAAoB,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;QACpE,MAAM,iBAAiB,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QAC9D,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAE1D,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QACrC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1D,IAAI,gBAAgB,GAAG,CAAC,CAAC;QACzB,IAAI,SAAS,GAAG,CAAC,CAAC;QAElB,qCAAqC;QACrC,IAAI,CAAC,uBAAuB,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;QAEzD,sEAAsE;QACtE,OAAO,iBAAiB,CAAC,IAAI,IAAI,eAAe,CAAC,IAAI,EAAE,CAAC;YACtD,gDAAgD;YAChD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,8BAA8B,EAAE,EAAE,CAAC;gBACzD,IAAI,CAAC,oBAAoB,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;YACpD,CAAC;YAED,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;gBAC1B,yEAAyE;gBACzE,mBAAmB;gBACnB,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;YAC5C,CAAC;YAED,uEAAuE;YACvE,IAAI,CAAC,sBAAsB,EAAE,CAAC;YAE9B,+CAA+C;YAC/C,MAAM,WAAW,GAAG,IAAI,CAAC,2BAA2B,EAAE,CAAC;YACvD,gBAAgB,IAAI,WAAW,CAAC;YAEhC,8EAA8E;YAC9E,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,SAAS,GAAG,MAAM,EAAE,CAAC;gBACxD,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;YACvD,CAAC;YAED,SAAS,EAAE,CAAC;YACZ,0DAA0D;YAC1D,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;gBACnC,IAAI,CAAC,+BAA+B,CAAC,IAAI,EAAE,WAAW,EAAE,gBAAgB,CAAC,CAAC;YAC5E,CAAC;QACH,CAAC;QAED,4FAA4F;QAC5F,MAAM,EAAC,WAAW,EAAE,mBAAmB,EAAC,GAAG,IAAI,CAAC,wBAAwB,EAAE,CAAC;QAC3E,2BAA2B,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,IAAI,WAAW,EAAE,mBAAmB,CAAC,CAAC;QAEnF,OAAO;YACL,QAAQ,EAAE,gBAAgB;YAC1B,WAAW;SACZ,CAAC;IACJ,CAAC;IAED,8BAA8B,CAAC,WAAmB;QAChD,MAAM,EAAC,UAAU,EAAE,kBAAkB,EAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;QAEvD,+EAA+E;QAC/E,iEAAiE;QACjE,kHAAkH;QAClH,MAAM,aAAa,GAAG,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,UAAU,CAAC;QACzE,IAAI,aAAa,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,CAAC;QACX,CAAC;QAED,MAAM,UAAU,GAAG,WAAW,GAAG,CAAC,CAAC;QACnC,MAAM,QAAQ,GAAG,UAAU,GAAG,aAAa,GAAG,IAAI,CAAC;QAEnD,6EAA6E;QAC7E,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC;IACxC,CAAC;IAED,MAAM,KAAK,cAAc;QACvB,OAAO,2BAA2B,CAAC;IACrC,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,yBAAyB,CAAC,IAAgB;QAC/C,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC,SAAS,CAAC;QACxB,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,GAAG,CAAC,wBAAwB,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC;IAC/F,CAAC;CACF;AAED,OAAO,EAAC,SAAS,EAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Graph from '../graph/graph.js';\nimport type * as Lantern from '../types/types.js';\n\nimport {ConnectionPool} from './ConnectionPool.js';\nimport {Constants} from './Constants.js';\nimport {DNSCache} from './DNSCache.js';\nimport {type CompleteNodeTiming, type ConnectionTiming, SimulatorTimingMap} from './SimulationTimingMap.js';\nimport {TCPConnection} from './TCPConnection.js';\n\nexport interface Result<T = Lantern.AnyNetworkObject> {\n timeInMs: number;\n nodeTimings: Map<Graph.Node<T>, Lantern.Simulation.NodeTiming>;\n}\n\nconst defaultThrottling = Constants.throttling.mobileSlow4G;\n\n// see https://cs.chromium.org/search/?q=kDefaultMaxNumDelayableRequestsPerClient&sq=package:chromium&type=cs\nconst DEFAULT_MAXIMUM_CONCURRENT_REQUESTS = 10;\n// layout tasks tend to be less CPU-bound and do not experience the same increase in duration\nconst DEFAULT_LAYOUT_TASK_MULTIPLIER = 0.5;\n// if a task takes more than 10 seconds it's usually a sign it isn't actually CPU bound and we're overestimating\nconst DEFAULT_MAXIMUM_CPU_TASK_DURATION = 10000;\n\nconst NodeState = {\n NotReadyToStart: 0,\n ReadyToStart: 1,\n InProgress: 2,\n Complete: 3,\n};\n\nconst PriorityStartTimePenalty: Record<Lantern.ResourcePriority, number> = {\n VeryHigh: 0,\n High: 0.25,\n Medium: 0.5,\n Low: 1,\n VeryLow: 2,\n};\n\nconst ALL_SIMULATION_NODE_TIMINGS = new Map<string, Map<Graph.Node, CompleteNodeTiming>>();\n\nclass Simulator<T = Lantern.AnyNetworkObject> {\n static createSimulator(settings: Lantern.Simulation.Settings): Simulator {\n const {throttlingMethod, throttling, precomputedLanternData, networkAnalysis} = settings;\n\n const options: Lantern.Simulation.Options = {\n additionalRttByOrigin: networkAnalysis.additionalRttByOrigin,\n serverResponseTimeByOrigin: networkAnalysis.serverResponseTimeByOrigin,\n observedThroughput: networkAnalysis.throughput,\n };\n\n // If we have precomputed lantern data, overwrite our observed estimates and use precomputed instead\n // for increased stability.\n if (precomputedLanternData) {\n options.additionalRttByOrigin = new Map(Object.entries(precomputedLanternData.additionalRttByOrigin));\n options.serverResponseTimeByOrigin = new Map(Object.entries(precomputedLanternData.serverResponseTimeByOrigin));\n }\n\n switch (throttlingMethod) {\n case 'provided':\n options.rtt = networkAnalysis.rtt;\n options.throughput = networkAnalysis.throughput;\n options.cpuSlowdownMultiplier = 1;\n options.layoutTaskMultiplier = 1;\n break;\n case 'devtools':\n if (throttling) {\n options.rtt = throttling.requestLatencyMs / Constants.throttling.DEVTOOLS_RTT_ADJUSTMENT_FACTOR;\n options.throughput =\n throttling.downloadThroughputKbps * 1024 / Constants.throttling.DEVTOOLS_THROUGHPUT_ADJUSTMENT_FACTOR;\n }\n\n options.cpuSlowdownMultiplier = 1;\n options.layoutTaskMultiplier = 1;\n break;\n case 'simulate':\n if (throttling) {\n options.rtt = throttling.rttMs;\n options.throughput = throttling.throughputKbps * 1024;\n options.cpuSlowdownMultiplier = throttling.cpuSlowdownMultiplier;\n }\n break;\n default:\n // intentionally fallback to simulator defaults\n break;\n }\n\n return new Simulator(options);\n }\n\n _options: Required<Lantern.Simulation.Options>;\n _rtt: number;\n _throughput: number;\n _maximumConcurrentRequests: number;\n _cpuSlowdownMultiplier: number;\n _layoutTaskMultiplier: number;\n _cachedNodeListByStartPosition: Graph.Node[];\n _nodeTimings: SimulatorTimingMap;\n _numberInProgressByType: Map<string, number>;\n _nodes: Record<number, Set<Graph.Node>>;\n _dns: DNSCache;\n _connectionPool: ConnectionPool;\n\n constructor(options?: Lantern.Simulation.Options) {\n this._options = Object.assign(\n {\n rtt: defaultThrottling.rttMs,\n throughput: defaultThrottling.throughputKbps * 1024,\n maximumConcurrentRequests: DEFAULT_MAXIMUM_CONCURRENT_REQUESTS,\n cpuSlowdownMultiplier: defaultThrottling.cpuSlowdownMultiplier,\n layoutTaskMultiplier: DEFAULT_LAYOUT_TASK_MULTIPLIER,\n additionalRttByOrigin: new Map(),\n serverResponseTimeByOrigin: new Map(),\n },\n options,\n );\n\n this._rtt = this._options.rtt;\n this._throughput = this._options.throughput;\n this._maximumConcurrentRequests = Math.max(\n Math.min(\n TCPConnection.maximumSaturatedConnections(this._rtt, this._throughput),\n this._options.maximumConcurrentRequests,\n ),\n 1);\n this._cpuSlowdownMultiplier = this._options.cpuSlowdownMultiplier;\n this._layoutTaskMultiplier = this._cpuSlowdownMultiplier * this._options.layoutTaskMultiplier;\n this._cachedNodeListByStartPosition = [];\n\n // Properties reset on every `.simulate` call but duplicated here for type checking\n this._nodeTimings = new SimulatorTimingMap();\n this._numberInProgressByType = new Map<string, number>();\n this._nodes = {};\n this._dns = new DNSCache({rtt: this._rtt});\n // @ts-expect-error\n this._connectionPool = null;\n\n if (!Number.isFinite(this._rtt)) {\n throw new Error(`Invalid rtt ${this._rtt}`);\n }\n if (!Number.isFinite(this._throughput)) {\n throw new Error(`Invalid rtt ${this._throughput}`);\n }\n }\n\n get rtt(): number {\n return this._rtt;\n }\n\n _initializeConnectionPool(graph: Graph.Node): void {\n const records: Lantern.NetworkRequest[] = [];\n graph.getRootNode().traverse(node => {\n if (node.type === Graph.BaseNode.types.NETWORK) {\n records.push(node.request);\n }\n });\n\n this._connectionPool = new ConnectionPool(records, this._options);\n }\n\n /**\n * Initializes the various state data structures such _nodeTimings and the _node Sets by state.\n */\n _initializeAuxiliaryData(): void {\n this._nodeTimings = new SimulatorTimingMap();\n this._numberInProgressByType = new Map();\n\n this._nodes = {};\n this._cachedNodeListByStartPosition = [];\n // NOTE: We don't actually need *all* of these sets, but the clarity that each node progresses\n // through the system is quite nice.\n for (const state of Object.values(NodeState)) {\n this._nodes[state] = new Set();\n }\n }\n\n _numberInProgress(type: string): number {\n return this._numberInProgressByType.get(type) || 0;\n }\n\n _markNodeAsReadyToStart(node: Graph.Node, queuedTime: number): void {\n const nodeStartPosition = Simulator._computeNodeStartPosition(node);\n const firstNodeIndexWithGreaterStartPosition = this._cachedNodeListByStartPosition.findIndex(\n candidate => Simulator._computeNodeStartPosition(candidate) > nodeStartPosition);\n const insertionIndex = firstNodeIndexWithGreaterStartPosition === -1 ? this._cachedNodeListByStartPosition.length :\n firstNodeIndexWithGreaterStartPosition;\n this._cachedNodeListByStartPosition.splice(insertionIndex, 0, node);\n\n this._nodes[NodeState.ReadyToStart].add(node);\n this._nodes[NodeState.NotReadyToStart].delete(node);\n this._nodeTimings.setReadyToStart(node, {queuedTime});\n }\n\n _markNodeAsInProgress(node: Graph.Node, startTime: number): void {\n const indexOfNodeToStart = this._cachedNodeListByStartPosition.indexOf(node);\n this._cachedNodeListByStartPosition.splice(indexOfNodeToStart, 1);\n\n this._nodes[NodeState.InProgress].add(node);\n this._nodes[NodeState.ReadyToStart].delete(node);\n this._numberInProgressByType.set(node.type, this._numberInProgress(node.type) + 1);\n this._nodeTimings.setInProgress(node, {startTime});\n }\n\n _markNodeAsComplete(node: Graph.Node, endTime: number, connectionTiming?: ConnectionTiming): void {\n this._nodes[NodeState.Complete].add(node);\n this._nodes[NodeState.InProgress].delete(node);\n this._numberInProgressByType.set(node.type, this._numberInProgress(node.type) - 1);\n this._nodeTimings.setCompleted(node, {endTime, connectionTiming});\n\n // Try to add all its dependents to the queue\n for (const dependent of node.getDependents()) {\n // Skip dependent node if one of its dependencies hasn't finished yet\n const dependencies = dependent.getDependencies();\n if (dependencies.some(dep => !this._nodes[NodeState.Complete].has(dep))) {\n continue;\n }\n\n // Otherwise add it to the queue\n this._markNodeAsReadyToStart(dependent, endTime);\n }\n }\n\n _acquireConnection(request: Lantern.NetworkRequest): TCPConnection|null {\n return this._connectionPool.acquire(request);\n }\n\n _getNodesSortedByStartPosition(): Graph.Node[] {\n // Make a copy so we don't skip nodes due to concurrent modification\n return Array.from(this._cachedNodeListByStartPosition);\n }\n\n _startNodeIfPossible(node: Graph.Node, totalElapsedTime: number): void {\n if (node.type === Graph.BaseNode.types.CPU) {\n // Start a CPU task if there's no other CPU task in process\n if (this._numberInProgress(node.type) === 0) {\n this._markNodeAsInProgress(node, totalElapsedTime);\n }\n\n return;\n }\n\n if (node.type !== Graph.BaseNode.types.NETWORK) {\n throw new Error('Unsupported');\n }\n\n // If a network request is connectionless, we can always start it, so skip the connection checks\n if (!node.isConnectionless) {\n // Start a network request if we're not at max requests and a connection is available\n const numberOfActiveRequests = this._numberInProgress(node.type);\n if (numberOfActiveRequests >= this._maximumConcurrentRequests) {\n return;\n }\n const connection = this._acquireConnection(node.request);\n if (!connection) {\n return;\n }\n }\n\n this._markNodeAsInProgress(node, totalElapsedTime);\n }\n\n /**\n * Updates each connection in use with the available throughput based on the number of network requests\n * currently in flight.\n */\n _updateNetworkCapacity(): void {\n const inFlight = this._numberInProgress(Graph.BaseNode.types.NETWORK);\n if (inFlight === 0) {\n return;\n }\n\n for (const connection of this._connectionPool.connectionsInUse()) {\n connection.setThroughput(this._throughput / inFlight);\n }\n }\n\n /**\n * Estimates the number of milliseconds remaining given current condidtions before the node is complete.\n */\n _estimateTimeRemaining(node: Graph.Node): number {\n if (node.type === Graph.BaseNode.types.CPU) {\n return this._estimateCPUTimeRemaining(node);\n }\n if (node.type === Graph.BaseNode.types.NETWORK) {\n return this._estimateNetworkTimeRemaining(node);\n }\n throw new Error('Unsupported');\n }\n\n _estimateCPUTimeRemaining(cpuNode: Graph.CPUNode): number {\n const timingData = this._nodeTimings.getCpuStarted(cpuNode);\n const multiplier = cpuNode.didPerformLayout() ? this._layoutTaskMultiplier : this._cpuSlowdownMultiplier;\n const totalDuration = Math.min(\n Math.round(cpuNode.duration / 1000 * multiplier),\n DEFAULT_MAXIMUM_CPU_TASK_DURATION,\n );\n const estimatedTimeElapsed = totalDuration - timingData.timeElapsed;\n this._nodeTimings.setCpuEstimated(cpuNode, {estimatedTimeElapsed});\n return estimatedTimeElapsed;\n }\n\n _estimateNetworkTimeRemaining(networkNode: Graph.NetworkNode): number {\n const request = networkNode.request;\n const timingData = this._nodeTimings.getNetworkStarted(networkNode);\n\n let timeElapsed = 0;\n if (networkNode.fromDiskCache) {\n // Rough access time for seeking to location on disk and reading sequentially.\n // 8ms per seek + 20ms/MB\n // @see http://norvig.com/21-days.html#answers\n const sizeInMb = (request.resourceSize || 0) / 1024 / 1024;\n timeElapsed = 8 + 20 * sizeInMb - timingData.timeElapsed;\n } else if (networkNode.isNonNetworkProtocol) {\n // Estimates for the overhead of a data URL in Chromium and the decoding time for base64-encoded data.\n // 2ms per request + 10ms/MB\n // @see traces on https://dopiaza.org/tools/datauri/examples/index.php\n const sizeInMb = (request.resourceSize || 0) / 1024 / 1024;\n timeElapsed = 2 + 10 * sizeInMb - timingData.timeElapsed;\n } else {\n const connection = this._connectionPool.acquireActiveConnectionFromRequest(request);\n const dnsResolutionTime = this._dns.getTimeUntilResolution(request, {\n requestedAt: timingData.startTime,\n shouldUpdateCache: true,\n });\n const timeAlreadyElapsed = timingData.timeElapsed;\n const calculation = connection.simulateDownloadUntil(\n request.transferSize - timingData.bytesDownloaded,\n {timeAlreadyElapsed, dnsResolutionTime, maximumTimeToElapse: Infinity},\n );\n\n timeElapsed = calculation.timeElapsed;\n }\n\n const estimatedTimeElapsed = timeElapsed + timingData.timeElapsedOvershoot;\n this._nodeTimings.setNetworkEstimated(networkNode, {estimatedTimeElapsed});\n return estimatedTimeElapsed;\n }\n\n /**\n * Computes and returns the minimum estimated completion time of the nodes currently in progress.\n */\n _findNextNodeCompletionTime(): number {\n let minimumTime = Infinity;\n for (const node of this._nodes[NodeState.InProgress]) {\n minimumTime = Math.min(minimumTime, this._estimateTimeRemaining(node));\n }\n\n return minimumTime;\n }\n\n /**\n * Given a time period, computes the progress toward completion that the node made durin that time.\n */\n _updateProgressMadeInTimePeriod(node: Graph.Node, timePeriodLength: number, totalElapsedTime: number): void {\n const timingData = this._nodeTimings.getInProgress(node);\n const isFinished = timingData.estimatedTimeElapsed === timePeriodLength;\n\n if (node.type === Graph.BaseNode.types.CPU || node.isConnectionless) {\n if (isFinished) {\n this._markNodeAsComplete(node, totalElapsedTime);\n } else {\n timingData.timeElapsed += timePeriodLength;\n }\n return;\n }\n\n if (node.type !== Graph.BaseNode.types.NETWORK) {\n throw new Error('Unsupported');\n }\n if (!('bytesDownloaded' in timingData)) {\n throw new Error('Invalid timing data');\n }\n\n const request = node.request;\n const connection = this._connectionPool.acquireActiveConnectionFromRequest(request);\n const dnsResolutionTime = this._dns.getTimeUntilResolution(request, {\n requestedAt: timingData.startTime,\n shouldUpdateCache: true,\n });\n const calculation = connection.simulateDownloadUntil(\n request.transferSize - timingData.bytesDownloaded,\n {\n dnsResolutionTime,\n timeAlreadyElapsed: timingData.timeElapsed,\n maximumTimeToElapse: timePeriodLength - timingData.timeElapsedOvershoot,\n },\n );\n\n connection.setCongestionWindow(calculation.congestionWindow);\n connection.setH2OverflowBytesDownloaded(calculation.extraBytesDownloaded);\n\n if (isFinished) {\n connection.setWarmed(true);\n this._connectionPool.release(request);\n this._markNodeAsComplete(node, totalElapsedTime, calculation.connectionTiming);\n } else {\n timingData.timeElapsed += calculation.timeElapsed;\n timingData.timeElapsedOvershoot += calculation.timeElapsed - timePeriodLength;\n timingData.bytesDownloaded += calculation.bytesDownloaded;\n }\n }\n\n _computeFinalNodeTimings(): {\n nodeTimings: Map<Graph.Node, Lantern.Simulation.NodeTiming>,\n completeNodeTimings: Map<Graph.Node, CompleteNodeTiming>,\n } {\n const completeNodeTimingEntries: Array<[Graph.Node, CompleteNodeTiming]> =\n this._nodeTimings.getNodes().map(node => {\n return [node, this._nodeTimings.getCompleted(node)];\n });\n\n // Most consumers will want the entries sorted by startTime, so insert them in that order\n completeNodeTimingEntries.sort((a, b) => a[1].startTime - b[1].startTime);\n\n // Trimmed version of type `Lantern.Simulation.NodeTiming`.\n const nodeTimingEntries: Array<[Graph.Node, Lantern.Simulation.NodeTiming]> =\n completeNodeTimingEntries.map(([node, timing]) => {\n return [\n node,\n {\n startTime: timing.startTime,\n endTime: timing.endTime,\n duration: timing.endTime - timing.startTime,\n },\n ];\n });\n\n return {\n nodeTimings: new Map(nodeTimingEntries),\n completeNodeTimings: new Map(completeNodeTimingEntries),\n };\n }\n\n getOptions(): Required<Lantern.Simulation.Options> {\n return this._options;\n }\n\n /**\n * Estimates the time taken to process all of the graph's nodes, returns the overall time along with\n * each node annotated by start/end times.\n *\n * Simulator/connection pool are allowed to deviate from what was\n * observed in the trace/devtoolsLog and start requests as soon as they are queued (i.e. do not\n * wait around for a warm connection to be available if the original request was fetched on a warm\n * connection).\n */\n simulate(graph: Graph.Node, options?: {label?: string}): Result<T> {\n if (Graph.BaseNode.hasCycle(graph)) {\n throw new Error('Cannot simulate graph with cycle');\n }\n\n options = Object.assign(\n {\n label: undefined,\n },\n options);\n\n // initialize the necessary data containers\n this._dns = new DNSCache({rtt: this._rtt});\n this._initializeConnectionPool(graph);\n this._initializeAuxiliaryData();\n\n const nodesNotReadyToStart = this._nodes[NodeState.NotReadyToStart];\n const nodesReadyToStart = this._nodes[NodeState.ReadyToStart];\n const nodesInProgress = this._nodes[NodeState.InProgress];\n\n const rootNode = graph.getRootNode();\n rootNode.traverse(node => nodesNotReadyToStart.add(node));\n let totalElapsedTime = 0;\n let iteration = 0;\n\n // root node is always ready to start\n this._markNodeAsReadyToStart(rootNode, totalElapsedTime);\n\n // loop as long as we have nodes in the queue or currently in progress\n while (nodesReadyToStart.size || nodesInProgress.size) {\n // move all possible queued nodes to in progress\n for (const node of this._getNodesSortedByStartPosition()) {\n this._startNodeIfPossible(node, totalElapsedTime);\n }\n\n if (!nodesInProgress.size) {\n // Interplay between fromDiskCache and connectionReused can be incorrect,\n // have to give up.\n throw new Error('Failed to start a node');\n }\n\n // set the available throughput for all connections based on # inflight\n this._updateNetworkCapacity();\n\n // find the time that the next node will finish\n const minimumTime = this._findNextNodeCompletionTime();\n totalElapsedTime += minimumTime;\n\n // While this is no longer strictly necessary, it's always better than hanging\n if (!Number.isFinite(minimumTime) || iteration > 100000) {\n throw new Error('Simulation failed, depth exceeded');\n }\n\n iteration++;\n // update how far each node will progress until that point\n for (const node of nodesInProgress) {\n this._updateProgressMadeInTimePeriod(node, minimumTime, totalElapsedTime);\n }\n }\n\n // `nodeTimings` are used for simulator consumers, `completeNodeTimings` kept for debugging.\n const {nodeTimings, completeNodeTimings} = this._computeFinalNodeTimings();\n ALL_SIMULATION_NODE_TIMINGS.set(options.label || 'unlabeled', completeNodeTimings);\n\n return {\n timeInMs: totalElapsedTime,\n nodeTimings,\n };\n }\n\n computeWastedMsFromWastedBytes(wastedBytes: number): number {\n const {throughput, observedThroughput} = this._options;\n\n // https://github.com/GoogleChrome/lighthouse/pull/13323#issuecomment-962031709\n // 0 throughput means the no (additional) throttling is expected.\n // This is common for desktop + devtools throttling where throttling is additive and we don't want any additional.\n const bitsPerSecond = throughput === 0 ? observedThroughput : throughput;\n if (bitsPerSecond === 0) {\n return 0;\n }\n\n const wastedBits = wastedBytes * 8;\n const wastedMs = wastedBits / bitsPerSecond * 1000;\n\n // This is an estimate of wasted time, so we won't be more precise than 10ms.\n return Math.round(wastedMs / 10) * 10;\n }\n\n static get allNodeTimings(): Map<string, Map<Graph.Node, CompleteNodeTiming>> {\n return ALL_SIMULATION_NODE_TIMINGS;\n }\n\n /**\n * We attempt to start nodes by their observed start time using the request priority as a tie breaker.\n * When simulating, just because a low priority image started 5ms before a high priority image doesn't mean\n * it would have happened like that when the network was slower.\n */\n static _computeNodeStartPosition(node: Graph.Node): number {\n if (node.type === 'cpu') {\n return node.startTime;\n }\n return node.startTime + (PriorityStartTimePenalty[node.request.priority] * 1000 * 1000 || 0);\n }\n}\n\nexport {Simulator};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"compilerOptions":{"composite":true,"outDir":".","baseUrl":".","rootDir":"../../../../../../../../front_end/models/trace/lantern/simulation"},"files":["../../../../../../../../front_end/models/trace/lantern/simulation/simulation.ts"],"references":[{"path":"./simulation-tsconfig.json"}]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"allowJs": true,
|
|
4
|
+
"checkJs": true,
|
|
5
|
+
"composite": true,
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"experimentalDecorators": true,
|
|
8
|
+
"forceConsistentCasingInFileNames": true,
|
|
9
|
+
"inlineSources": true,
|
|
10
|
+
"lib": [
|
|
11
|
+
"esnext",
|
|
12
|
+
"dom",
|
|
13
|
+
"dom.iterable"
|
|
14
|
+
],
|
|
15
|
+
"module": "esnext",
|
|
16
|
+
"noEmitOnError": true,
|
|
17
|
+
"noFallthroughCasesInSwitch": true,
|
|
18
|
+
"noImplicitOverride": true,
|
|
19
|
+
"noImplicitReturns": true,
|
|
20
|
+
"noUnusedLocals": false,
|
|
21
|
+
"outDir": ".",
|
|
22
|
+
"rootDir": "../../../../../../../../front_end/models/trace/lantern/simulation",
|
|
23
|
+
"skipLibCheck": true,
|
|
24
|
+
"sourceMap": true,
|
|
25
|
+
"strict": true,
|
|
26
|
+
"target": "esnext",
|
|
27
|
+
"tsBuildInfoFile": "devtools_entrypoint-bundle-typescript-tsconfig.json.tsbuildinfo",
|
|
28
|
+
"typeRoots": [],
|
|
29
|
+
"useUnknownInCatchVariables": false
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"../../../../../../../../front_end/models/trace/lantern/simulation/simulation.ts",
|
|
33
|
+
"../../../../../../../../front_end/legacy/legacy-defs.d.ts",
|
|
34
|
+
"../../../../../../../../front_end/global_typings/global_defs.d.ts",
|
|
35
|
+
"../../../../../../../../node_modules/@types/filesystem/index.d.ts"
|
|
36
|
+
],
|
|
37
|
+
"references": [
|
|
38
|
+
{
|
|
39
|
+
"path": "./simulation-tsconfig.json"
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"allowJs": true,
|
|
4
|
+
"checkJs": true,
|
|
5
|
+
"composite": true,
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"experimentalDecorators": true,
|
|
8
|
+
"forceConsistentCasingInFileNames": true,
|
|
9
|
+
"inlineSources": true,
|
|
10
|
+
"lib": [
|
|
11
|
+
"esnext",
|
|
12
|
+
"dom",
|
|
13
|
+
"dom.iterable"
|
|
14
|
+
],
|
|
15
|
+
"module": "esnext",
|
|
16
|
+
"noEmitOnError": true,
|
|
17
|
+
"noFallthroughCasesInSwitch": true,
|
|
18
|
+
"noImplicitOverride": true,
|
|
19
|
+
"noImplicitReturns": true,
|
|
20
|
+
"noUnusedLocals": false,
|
|
21
|
+
"outDir": ".",
|
|
22
|
+
"rootDir": "../../../../../../../../front_end/models/trace/lantern/simulation",
|
|
23
|
+
"skipLibCheck": true,
|
|
24
|
+
"sourceMap": true,
|
|
25
|
+
"strict": true,
|
|
26
|
+
"target": "esnext",
|
|
27
|
+
"tsBuildInfoFile": "simulation-tsconfig.json.tsbuildinfo",
|
|
28
|
+
"typeRoots": [],
|
|
29
|
+
"useUnknownInCatchVariables": false
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"../../../../../../../../front_end/models/trace/lantern/simulation/ConnectionPool.ts",
|
|
33
|
+
"../../../../../../../../front_end/models/trace/lantern/simulation/Constants.ts",
|
|
34
|
+
"../../../../../../../../front_end/models/trace/lantern/simulation/DNSCache.ts",
|
|
35
|
+
"../../../../../../../../front_end/models/trace/lantern/simulation/SimulationTimingMap.ts",
|
|
36
|
+
"../../../../../../../../front_end/models/trace/lantern/simulation/Simulator.ts",
|
|
37
|
+
"../../../../../../../../front_end/models/trace/lantern/simulation/TCPConnection.ts",
|
|
38
|
+
"../../../../../../../../front_end/legacy/legacy-defs.d.ts",
|
|
39
|
+
"../../../../../../../../front_end/global_typings/global_defs.d.ts",
|
|
40
|
+
"../../../../../../../../node_modules/@types/filesystem/index.d.ts"
|
|
41
|
+
],
|
|
42
|
+
"references": [
|
|
43
|
+
{
|
|
44
|
+
"path": "../graph/bundle-tsconfig.json"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"path": "../types/bundle-tsconfig.json"
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
}
|