@paulirish/trace_engine 0.0.25 → 0.0.27
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/core/platform/TypedArrayUtilities.d.ts +7 -0
- package/core/platform/TypedArrayUtilities.js +41 -0
- package/core/platform/TypedArrayUtilities.js.map +1 -1
- package/core/platform/devtools_entrypoint-bundle-typescript-tsconfig.json +0 -1
- package/core/platform/platform-tsconfig.json +0 -1
- package/generated/protocol.d.ts +36 -2
- package/models/cpu_profile/cpu_profile-tsconfig.json +0 -1
- package/models/cpu_profile/devtools_entrypoint-bundle-typescript-tsconfig.json +0 -1
- package/models/trace/LanternComputationData.d.ts +8 -0
- package/models/trace/LanternComputationData.js +368 -0
- package/models/trace/LanternComputationData.js.map +1 -0
- package/models/trace/devtools_entrypoint-bundle-typescript-tsconfig.json +0 -1
- package/models/trace/extras/devtools_entrypoint-bundle-typescript-tsconfig.json +0 -1
- package/models/trace/extras/extras-tsconfig.json +0 -1
- package/models/trace/handlers/EnhancedTracesHandler.d.ts +46 -0
- package/models/trace/handlers/EnhancedTracesHandler.js +137 -0
- package/models/trace/handlers/EnhancedTracesHandler.js.map +1 -0
- package/models/trace/handlers/LayoutShiftsHandler.d.ts +1 -1
- package/models/trace/handlers/LayoutShiftsHandler.js +1 -1
- package/models/trace/handlers/LayoutShiftsHandler.js.map +1 -1
- package/models/trace/handlers/ModelHandlers.d.ts +1 -0
- package/models/trace/handlers/ModelHandlers.js +1 -0
- package/models/trace/handlers/ModelHandlers.js.map +1 -1
- package/models/trace/handlers/UserInteractionsHandler.d.ts +6 -0
- package/models/trace/handlers/UserInteractionsHandler.js +15 -0
- package/models/trace/handlers/UserInteractionsHandler.js.map +1 -1
- package/models/trace/handlers/devtools_entrypoint-bundle-typescript-tsconfig.json +0 -1
- package/models/trace/handlers/handlers-tsconfig.json +1 -1
- package/models/trace/helpers/Timing.d.ts +0 -6
- package/models/trace/helpers/Timing.js +0 -76
- package/models/trace/helpers/Timing.js.map +1 -1
- package/models/trace/helpers/devtools_entrypoint-bundle-typescript-tsconfig.json +0 -1
- package/models/trace/helpers/helpers-tsconfig.json +0 -1
- package/models/trace/insights/devtools_entrypoint-bundle-typescript-tsconfig.json +0 -1
- package/models/trace/insights/insights-tsconfig.json +0 -1
- package/models/trace/lantern/BaseNode.d.ts +91 -0
- package/models/trace/lantern/BaseNode.js +268 -0
- package/models/trace/lantern/BaseNode.js.map +1 -0
- package/models/trace/lantern/CPUNode.d.ts +24 -0
- package/models/trace/lantern/CPUNode.js +64 -0
- package/models/trace/lantern/CPUNode.js.map +1 -0
- package/models/trace/lantern/LanternError.d.ts +3 -0
- package/models/trace/lantern/LanternError.js +7 -0
- package/models/trace/lantern/LanternError.js.map +1 -0
- package/models/trace/lantern/MetricsModule.d.ts +11 -0
- package/models/trace/lantern/MetricsModule.js +14 -0
- package/models/trace/lantern/MetricsModule.js.map +1 -0
- package/models/trace/lantern/NetworkNode.d.ts +22 -0
- package/models/trace/lantern/NetworkNode.js +83 -0
- package/models/trace/lantern/NetworkNode.js.map +1 -0
- package/models/trace/lantern/PageDependencyGraph.d.ts +43 -0
- package/models/trace/lantern/PageDependencyGraph.js +509 -0
- package/models/trace/lantern/PageDependencyGraph.js.map +1 -0
- package/models/trace/lantern/SimulationModule.d.ts +17 -0
- package/models/trace/lantern/SimulationModule.js +13 -0
- package/models/trace/lantern/SimulationModule.js.map +1 -0
- package/models/trace/lantern/bundle-tsconfig.json +1 -0
- 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/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 +53 -0
- package/models/trace/lantern/lantern.d.ts +6 -0
- package/models/trace/lantern/lantern.js +10 -0
- package/models/trace/lantern/lantern.js.map +1 -0
- package/models/trace/lantern/metrics/FirstContentfulPaint.d.ts +40 -0
- package/models/trace/lantern/metrics/FirstContentfulPaint.js +137 -0
- package/models/trace/lantern/metrics/FirstContentfulPaint.js.map +1 -0
- package/models/trace/lantern/metrics/Interactive.d.ts +12 -0
- package/models/trace/lantern/metrics/Interactive.js +67 -0
- package/models/trace/lantern/metrics/Interactive.js.map +1 -0
- package/models/trace/lantern/metrics/LargestContentfulPaint.d.ts +17 -0
- package/models/trace/lantern/metrics/LargestContentfulPaint.js +69 -0
- package/models/trace/lantern/metrics/LargestContentfulPaint.js.map +1 -0
- package/models/trace/lantern/metrics/MaxPotentialFID.d.ts +14 -0
- package/models/trace/lantern/metrics/MaxPotentialFID.js +48 -0
- package/models/trace/lantern/metrics/MaxPotentialFID.js.map +1 -0
- package/models/trace/lantern/metrics/Metric.d.ts +44 -0
- package/models/trace/lantern/metrics/Metric.js +70 -0
- package/models/trace/lantern/metrics/Metric.js.map +1 -0
- package/models/trace/lantern/metrics/SpeedIndex.d.ts +25 -0
- package/models/trace/lantern/metrics/SpeedIndex.js +101 -0
- package/models/trace/lantern/metrics/SpeedIndex.js.map +1 -0
- package/models/trace/lantern/metrics/TBTUtils.d.ts +31 -0
- package/models/trace/lantern/metrics/TBTUtils.js +65 -0
- package/models/trace/lantern/metrics/TBTUtils.js.map +1 -0
- package/models/trace/lantern/metrics/TotalBlockingTime.d.ts +16 -0
- package/models/trace/lantern/metrics/TotalBlockingTime.js +78 -0
- package/models/trace/lantern/metrics/TotalBlockingTime.js.map +1 -0
- 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 +8 -0
- package/models/trace/lantern/metrics/metrics.js +12 -0
- package/models/trace/lantern/metrics/metrics.js.map +1 -0
- package/models/trace/lantern/simulation/ConnectionPool.d.ts +26 -0
- package/models/trace/lantern/simulation/ConnectionPool.js +116 -0
- package/models/trace/lantern/simulation/ConnectionPool.js.map +1 -0
- package/models/trace/lantern/simulation/Constants.d.ts +31 -0
- package/models/trace/lantern/simulation/Constants.js +43 -0
- package/models/trace/lantern/simulation/Constants.js.map +1 -0
- package/models/trace/lantern/simulation/DNSCache.d.ts +22 -0
- package/models/trace/lantern/simulation/DNSCache.js +48 -0
- package/models/trace/lantern/simulation/DNSCache.js.map +1 -0
- package/models/trace/lantern/simulation/NetworkAnalyzer.d.ts +112 -0
- package/models/trace/lantern/simulation/NetworkAnalyzer.js +486 -0
- package/models/trace/lantern/simulation/NetworkAnalyzer.js.map +1 -0
- package/models/trace/lantern/simulation/SimulationTimingMap.d.ts +69 -0
- package/models/trace/lantern/simulation/SimulationTimingMap.js +134 -0
- package/models/trace/lantern/simulation/SimulationTimingMap.js.map +1 -0
- package/models/trace/lantern/simulation/Simulator.d.ts +84 -0
- package/models/trace/lantern/simulation/Simulator.js +449 -0
- package/models/trace/lantern/simulation/Simulator.js.map +1 -0
- package/models/trace/lantern/simulation/TCPConnection.d.ts +48 -0
- package/models/trace/lantern/simulation/TCPConnection.js +158 -0
- package/models/trace/lantern/simulation/TCPConnection.js.map +1 -0
- 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 -0
- package/models/trace/lantern/simulation/simulation.js +10 -0
- package/models/trace/lantern/simulation/simulation.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/lantern.d.ts +199 -0
- package/models/trace/lantern/types/lantern.js +24 -0
- package/models/trace/lantern/types/lantern.js.map +1 -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/types.js +5 -0
- package/models/trace/lantern/types/types.js.map +1 -0
- package/models/trace/root-causes/devtools_entrypoint-bundle-typescript-tsconfig.json +0 -1
- package/models/trace/root-causes/root-causes-tsconfig.json +0 -1
- package/models/trace/trace-tsconfig.json +4 -1
- package/models/trace/trace.d.ts +3 -1
- package/models/trace/trace.js +3 -1
- package/models/trace/trace.js.map +1 -1
- package/models/trace/types/Extensions.d.ts +2 -3
- package/models/trace/types/Extensions.js +2 -11
- package/models/trace/types/Extensions.js.map +1 -1
- package/models/trace/types/File.d.ts +1 -0
- package/models/trace/types/File.js.map +1 -1
- package/models/trace/types/TraceEvents.d.ts +49 -0
- package/models/trace/types/TraceEvents.js +33 -0
- package/models/trace/types/TraceEvents.js.map +1 -1
- package/models/trace/types/devtools_entrypoint-bundle-typescript-tsconfig.json +0 -1
- package/models/trace/types/types-tsconfig.json +0 -1
- package/package.json +1 -1
- package/PAUL.readme.md +0 -5
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type * as Lantern from '../types/types.js';
|
|
2
|
+
import { TCPConnection } from './TCPConnection.js';
|
|
3
|
+
export declare class ConnectionPool {
|
|
4
|
+
_options: Required<Lantern.Simulation.Options>;
|
|
5
|
+
_records: Lantern.NetworkRequest[];
|
|
6
|
+
_connectionsByOrigin: Map<string, TCPConnection[]>;
|
|
7
|
+
_connectionsByRequest: Map<Lantern.NetworkRequest, TCPConnection>;
|
|
8
|
+
_connectionsInUse: Set<TCPConnection>;
|
|
9
|
+
_connectionReusedByRequestId: Map<string, boolean>;
|
|
10
|
+
constructor(records: Lantern.NetworkRequest[], options: Required<Lantern.Simulation.Options>);
|
|
11
|
+
connectionsInUse(): TCPConnection[];
|
|
12
|
+
_initializeConnections(): void;
|
|
13
|
+
_findAvailableConnectionWithLargestCongestionWindow(connections: TCPConnection[]): TCPConnection | null;
|
|
14
|
+
/**
|
|
15
|
+
* This method finds an available connection to the origin specified by the network request or null
|
|
16
|
+
* if no connection was available. If returned, connection will not be available for other network
|
|
17
|
+
* records until release is called.
|
|
18
|
+
*/
|
|
19
|
+
acquire(request: Lantern.NetworkRequest): TCPConnection | null;
|
|
20
|
+
/**
|
|
21
|
+
* Return the connection currently being used to fetch a request. If no connection
|
|
22
|
+
* currently being used for this request, an error will be thrown.
|
|
23
|
+
*/
|
|
24
|
+
acquireActiveConnectionFromRequest(request: Lantern.NetworkRequest): TCPConnection;
|
|
25
|
+
release(request: Lantern.NetworkRequest): void;
|
|
26
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// Copyright 2024 The Chromium Authors. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
import * as Core from '../core/core.js';
|
|
5
|
+
import { TCPConnection } from './TCPConnection.js';
|
|
6
|
+
const DEFAULT_SERVER_RESPONSE_TIME = 30;
|
|
7
|
+
const TLS_SCHEMES = ['https', 'wss'];
|
|
8
|
+
// Each origin can have 6 simulatenous connections open
|
|
9
|
+
// https://cs.chromium.org/chromium/src/net/socket/client_socket_pool_manager.cc?type=cs&q="int+g_max_sockets_per_group"
|
|
10
|
+
const CONNECTIONS_PER_ORIGIN = 6;
|
|
11
|
+
export class ConnectionPool {
|
|
12
|
+
_options;
|
|
13
|
+
_records;
|
|
14
|
+
_connectionsByOrigin;
|
|
15
|
+
_connectionsByRequest;
|
|
16
|
+
_connectionsInUse;
|
|
17
|
+
_connectionReusedByRequestId;
|
|
18
|
+
constructor(records, options) {
|
|
19
|
+
this._options = options;
|
|
20
|
+
this._records = records;
|
|
21
|
+
this._connectionsByOrigin = new Map();
|
|
22
|
+
this._connectionsByRequest = new Map();
|
|
23
|
+
this._connectionsInUse = new Set();
|
|
24
|
+
this._connectionReusedByRequestId = Core.NetworkAnalyzer.estimateIfConnectionWasReused(records, {
|
|
25
|
+
forceCoarseEstimates: true,
|
|
26
|
+
});
|
|
27
|
+
this._initializeConnections();
|
|
28
|
+
}
|
|
29
|
+
connectionsInUse() {
|
|
30
|
+
return Array.from(this._connectionsInUse);
|
|
31
|
+
}
|
|
32
|
+
_initializeConnections() {
|
|
33
|
+
const connectionReused = this._connectionReusedByRequestId;
|
|
34
|
+
const additionalRttByOrigin = this._options.additionalRttByOrigin;
|
|
35
|
+
const serverResponseTimeByOrigin = this._options.serverResponseTimeByOrigin;
|
|
36
|
+
const recordsByOrigin = Core.NetworkAnalyzer.groupByOrigin(this._records);
|
|
37
|
+
for (const [origin, requests] of recordsByOrigin.entries()) {
|
|
38
|
+
const connections = [];
|
|
39
|
+
const additionalRtt = additionalRttByOrigin.get(origin) || 0;
|
|
40
|
+
const responseTime = serverResponseTimeByOrigin.get(origin) || DEFAULT_SERVER_RESPONSE_TIME;
|
|
41
|
+
for (const request of requests) {
|
|
42
|
+
if (connectionReused.get(request.requestId)) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const isTLS = TLS_SCHEMES.includes(request.parsedURL.scheme);
|
|
46
|
+
const isH2 = request.protocol === 'h2';
|
|
47
|
+
const connection = new TCPConnection(this._options.rtt + additionalRtt, this._options.throughput, responseTime, isTLS, isH2);
|
|
48
|
+
connections.push(connection);
|
|
49
|
+
}
|
|
50
|
+
if (!connections.length) {
|
|
51
|
+
throw new Error(`Could not find a connection for origin: ${origin}`);
|
|
52
|
+
}
|
|
53
|
+
// Make sure each origin has minimum number of connections available for max throughput.
|
|
54
|
+
// But only if it's not over H2 which maximizes throughput already.
|
|
55
|
+
const minConnections = connections[0].isH2() ? 1 : CONNECTIONS_PER_ORIGIN;
|
|
56
|
+
while (connections.length < minConnections) {
|
|
57
|
+
connections.push(connections[0].clone());
|
|
58
|
+
}
|
|
59
|
+
this._connectionsByOrigin.set(origin, connections);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
_findAvailableConnectionWithLargestCongestionWindow(connections) {
|
|
63
|
+
let maxConnection = null;
|
|
64
|
+
for (let i = 0; i < connections.length; i++) {
|
|
65
|
+
const connection = connections[i];
|
|
66
|
+
// Connections that are in use are never available.
|
|
67
|
+
if (this._connectionsInUse.has(connection)) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
// This connection is a match and is available! Update our max if it has a larger congestionWindow
|
|
71
|
+
const currentMax = (maxConnection?.congestionWindow) || -Infinity;
|
|
72
|
+
if (connection.congestionWindow > currentMax) {
|
|
73
|
+
maxConnection = connection;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return maxConnection;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* This method finds an available connection to the origin specified by the network request or null
|
|
80
|
+
* if no connection was available. If returned, connection will not be available for other network
|
|
81
|
+
* records until release is called.
|
|
82
|
+
*/
|
|
83
|
+
acquire(request) {
|
|
84
|
+
if (this._connectionsByRequest.has(request)) {
|
|
85
|
+
throw new Error('Record already has a connection');
|
|
86
|
+
}
|
|
87
|
+
const origin = request.parsedURL.securityOrigin;
|
|
88
|
+
const connections = this._connectionsByOrigin.get(origin) || [];
|
|
89
|
+
const connectionToUse = this._findAvailableConnectionWithLargestCongestionWindow(connections);
|
|
90
|
+
if (!connectionToUse) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
this._connectionsInUse.add(connectionToUse);
|
|
94
|
+
this._connectionsByRequest.set(request, connectionToUse);
|
|
95
|
+
return connectionToUse;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Return the connection currently being used to fetch a request. If no connection
|
|
99
|
+
* currently being used for this request, an error will be thrown.
|
|
100
|
+
*/
|
|
101
|
+
acquireActiveConnectionFromRequest(request) {
|
|
102
|
+
const activeConnection = this._connectionsByRequest.get(request);
|
|
103
|
+
if (!activeConnection) {
|
|
104
|
+
throw new Error('Could not find an active connection for request');
|
|
105
|
+
}
|
|
106
|
+
return activeConnection;
|
|
107
|
+
}
|
|
108
|
+
release(request) {
|
|
109
|
+
const connection = this._connectionsByRequest.get(request);
|
|
110
|
+
this._connectionsByRequest.delete(request);
|
|
111
|
+
if (connection) {
|
|
112
|
+
this._connectionsInUse.delete(connection);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=ConnectionPool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConnectionPool.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/simulation/ConnectionPool.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Core from '../core/core.js';\nimport type * as Lantern from '../types/types.js';\n\nimport {TCPConnection} from './TCPConnection.js';\n\nconst DEFAULT_SERVER_RESPONSE_TIME = 30;\nconst TLS_SCHEMES = ['https', 'wss'];\n\n// Each origin can have 6 simulatenous connections open\n// https://cs.chromium.org/chromium/src/net/socket/client_socket_pool_manager.cc?type=cs&q=\"int+g_max_sockets_per_group\"\nconst CONNECTIONS_PER_ORIGIN = 6;\n\nexport class ConnectionPool {\n _options: Required<Lantern.Simulation.Options>;\n _records: Lantern.NetworkRequest[];\n _connectionsByOrigin: Map<string, TCPConnection[]>;\n _connectionsByRequest: Map<Lantern.NetworkRequest, TCPConnection>;\n _connectionsInUse: Set<TCPConnection>;\n _connectionReusedByRequestId: Map<string, boolean>;\n\n constructor(records: Lantern.NetworkRequest[], options: Required<Lantern.Simulation.Options>) {\n this._options = options;\n\n this._records = records;\n this._connectionsByOrigin = new Map();\n this._connectionsByRequest = new Map();\n this._connectionsInUse = new Set();\n this._connectionReusedByRequestId = Core.NetworkAnalyzer.estimateIfConnectionWasReused(records, {\n forceCoarseEstimates: true,\n });\n\n this._initializeConnections();\n }\n\n connectionsInUse(): TCPConnection[] {\n return Array.from(this._connectionsInUse);\n }\n\n _initializeConnections(): void {\n const connectionReused = this._connectionReusedByRequestId;\n const additionalRttByOrigin = this._options.additionalRttByOrigin;\n const serverResponseTimeByOrigin = this._options.serverResponseTimeByOrigin;\n\n const recordsByOrigin = Core.NetworkAnalyzer.groupByOrigin(this._records);\n for (const [origin, requests] of recordsByOrigin.entries()) {\n const connections = [];\n const additionalRtt = additionalRttByOrigin.get(origin) || 0;\n const responseTime = serverResponseTimeByOrigin.get(origin) || DEFAULT_SERVER_RESPONSE_TIME;\n\n for (const request of requests) {\n if (connectionReused.get(request.requestId)) {\n continue;\n }\n\n const isTLS = TLS_SCHEMES.includes(request.parsedURL.scheme);\n const isH2 = request.protocol === 'h2';\n const connection = new TCPConnection(\n this._options.rtt + additionalRtt,\n this._options.throughput,\n responseTime,\n isTLS,\n isH2,\n );\n\n connections.push(connection);\n }\n\n if (!connections.length) {\n throw new Error(`Could not find a connection for origin: ${origin}`);\n }\n\n // Make sure each origin has minimum number of connections available for max throughput.\n // But only if it's not over H2 which maximizes throughput already.\n const minConnections = connections[0].isH2() ? 1 : CONNECTIONS_PER_ORIGIN;\n while (connections.length < minConnections) {\n connections.push(connections[0].clone());\n }\n\n this._connectionsByOrigin.set(origin, connections);\n }\n }\n\n _findAvailableConnectionWithLargestCongestionWindow(connections: TCPConnection[]): TCPConnection|null {\n let maxConnection: TCPConnection|null = null;\n for (let i = 0; i < connections.length; i++) {\n const connection = connections[i];\n\n // Connections that are in use are never available.\n if (this._connectionsInUse.has(connection)) {\n continue;\n }\n\n // This connection is a match and is available! Update our max if it has a larger congestionWindow\n const currentMax = (maxConnection?.congestionWindow) || -Infinity;\n if (connection.congestionWindow > currentMax) {\n maxConnection = connection;\n }\n }\n\n return maxConnection;\n }\n\n /**\n * This method finds an available connection to the origin specified by the network request or null\n * if no connection was available. If returned, connection will not be available for other network\n * records until release is called.\n */\n acquire(request: Lantern.NetworkRequest): TCPConnection|null {\n if (this._connectionsByRequest.has(request)) {\n throw new Error('Record already has a connection');\n }\n\n const origin = request.parsedURL.securityOrigin;\n const connections = this._connectionsByOrigin.get(origin) || [];\n const connectionToUse = this._findAvailableConnectionWithLargestCongestionWindow(connections);\n\n if (!connectionToUse) {\n return null;\n }\n\n this._connectionsInUse.add(connectionToUse);\n this._connectionsByRequest.set(request, connectionToUse);\n return connectionToUse;\n }\n\n /**\n * Return the connection currently being used to fetch a request. If no connection\n * currently being used for this request, an error will be thrown.\n */\n acquireActiveConnectionFromRequest(request: Lantern.NetworkRequest): TCPConnection {\n const activeConnection = this._connectionsByRequest.get(request);\n if (!activeConnection) {\n throw new Error('Could not find an active connection for request');\n }\n\n return activeConnection;\n }\n\n release(request: Lantern.NetworkRequest): void {\n const connection = this._connectionsByRequest.get(request);\n this._connectionsByRequest.delete(request);\n if (connection) {\n this._connectionsInUse.delete(connection);\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
declare const Constants: {
|
|
2
|
+
throttling: {
|
|
3
|
+
DEVTOOLS_RTT_ADJUSTMENT_FACTOR: number;
|
|
4
|
+
DEVTOOLS_THROUGHPUT_ADJUSTMENT_FACTOR: number;
|
|
5
|
+
mobileSlow4G: {
|
|
6
|
+
rttMs: number;
|
|
7
|
+
throughputKbps: number;
|
|
8
|
+
requestLatencyMs: number;
|
|
9
|
+
downloadThroughputKbps: number;
|
|
10
|
+
uploadThroughputKbps: number;
|
|
11
|
+
cpuSlowdownMultiplier: number;
|
|
12
|
+
};
|
|
13
|
+
mobileRegular3G: {
|
|
14
|
+
rttMs: number;
|
|
15
|
+
throughputKbps: number;
|
|
16
|
+
requestLatencyMs: number;
|
|
17
|
+
downloadThroughputKbps: number;
|
|
18
|
+
uploadThroughputKbps: number;
|
|
19
|
+
cpuSlowdownMultiplier: number;
|
|
20
|
+
};
|
|
21
|
+
desktopDense4G: {
|
|
22
|
+
rttMs: number;
|
|
23
|
+
throughputKbps: number;
|
|
24
|
+
cpuSlowdownMultiplier: number;
|
|
25
|
+
requestLatencyMs: number;
|
|
26
|
+
downloadThroughputKbps: number;
|
|
27
|
+
uploadThroughputKbps: number;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
export { Constants };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Copyright 2024 The Chromium Authors. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
const DEVTOOLS_RTT_ADJUSTMENT_FACTOR = 3.75;
|
|
5
|
+
const DEVTOOLS_THROUGHPUT_ADJUSTMENT_FACTOR = 0.9;
|
|
6
|
+
const throttling = {
|
|
7
|
+
DEVTOOLS_RTT_ADJUSTMENT_FACTOR,
|
|
8
|
+
DEVTOOLS_THROUGHPUT_ADJUSTMENT_FACTOR,
|
|
9
|
+
// These values align with WebPageTest's definition of "Fast 3G"
|
|
10
|
+
// But offer similar characteristics to roughly the 75th percentile of 4G connections.
|
|
11
|
+
mobileSlow4G: {
|
|
12
|
+
rttMs: 150,
|
|
13
|
+
throughputKbps: 1.6 * 1024,
|
|
14
|
+
requestLatencyMs: 150 * DEVTOOLS_RTT_ADJUSTMENT_FACTOR,
|
|
15
|
+
downloadThroughputKbps: 1.6 * 1024 * DEVTOOLS_THROUGHPUT_ADJUSTMENT_FACTOR,
|
|
16
|
+
uploadThroughputKbps: 750 * DEVTOOLS_THROUGHPUT_ADJUSTMENT_FACTOR,
|
|
17
|
+
cpuSlowdownMultiplier: 4,
|
|
18
|
+
},
|
|
19
|
+
// These values partially align with WebPageTest's definition of "Regular 3G".
|
|
20
|
+
// These values are meant to roughly align with Chrome UX report's 3G definition which are based
|
|
21
|
+
// on HTTP RTT of 300-1400ms and downlink throughput of <700kbps.
|
|
22
|
+
mobileRegular3G: {
|
|
23
|
+
rttMs: 300,
|
|
24
|
+
throughputKbps: 700,
|
|
25
|
+
requestLatencyMs: 300 * DEVTOOLS_RTT_ADJUSTMENT_FACTOR,
|
|
26
|
+
downloadThroughputKbps: 700 * DEVTOOLS_THROUGHPUT_ADJUSTMENT_FACTOR,
|
|
27
|
+
uploadThroughputKbps: 700 * DEVTOOLS_THROUGHPUT_ADJUSTMENT_FACTOR,
|
|
28
|
+
cpuSlowdownMultiplier: 4,
|
|
29
|
+
},
|
|
30
|
+
// Using a "broadband" connection type
|
|
31
|
+
// Corresponds to "Dense 4G 25th percentile" in https://docs.google.com/document/d/1Ft1Bnq9-t4jK5egLSOc28IL4TvR-Tt0se_1faTA4KTY/edit#heading=h.bb7nfy2x9e5v
|
|
32
|
+
desktopDense4G: {
|
|
33
|
+
rttMs: 40,
|
|
34
|
+
throughputKbps: 10 * 1024,
|
|
35
|
+
cpuSlowdownMultiplier: 1,
|
|
36
|
+
requestLatencyMs: 0, // 0 means unset
|
|
37
|
+
downloadThroughputKbps: 0,
|
|
38
|
+
uploadThroughputKbps: 0,
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
const Constants = { throttling };
|
|
42
|
+
export { Constants };
|
|
43
|
+
//# sourceMappingURL=Constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Constants.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/simulation/Constants.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,MAAM,8BAA8B,GAAG,IAAI,CAAC;AAC5C,MAAM,qCAAqC,GAAG,GAAG,CAAC;AAElD,MAAM,UAAU,GAAG;IACjB,8BAA8B;IAC9B,qCAAqC;IACrC,gEAAgE;IAChE,sFAAsF;IACtF,YAAY,EAAE;QACZ,KAAK,EAAE,GAAG;QACV,cAAc,EAAE,GAAG,GAAG,IAAI;QAC1B,gBAAgB,EAAE,GAAG,GAAG,8BAA8B;QACtD,sBAAsB,EAAE,GAAG,GAAG,IAAI,GAAG,qCAAqC;QAC1E,oBAAoB,EAAE,GAAG,GAAG,qCAAqC;QACjE,qBAAqB,EAAE,CAAC;KACzB;IACD,8EAA8E;IAC9E,gGAAgG;IAChG,iEAAiE;IACjE,eAAe,EAAE;QACf,KAAK,EAAE,GAAG;QACV,cAAc,EAAE,GAAG;QACnB,gBAAgB,EAAE,GAAG,GAAG,8BAA8B;QACtD,sBAAsB,EAAE,GAAG,GAAG,qCAAqC;QACnE,oBAAoB,EAAE,GAAG,GAAG,qCAAqC;QACjE,qBAAqB,EAAE,CAAC;KACzB;IACD,sCAAsC;IACtC,2JAA2J;IAC3J,cAAc,EAAE;QACd,KAAK,EAAE,EAAE;QACT,cAAc,EAAE,EAAE,GAAG,IAAI;QACzB,qBAAqB,EAAE,CAAC;QACxB,gBAAgB,EAAE,CAAC,EAAG,gBAAgB;QACtC,sBAAsB,EAAE,CAAC;QACzB,oBAAoB,EAAE,CAAC;KACxB;CACF,CAAC;AAEF,MAAM,SAAS,GAAG,EAAC,UAAU,EAAC,CAAC;AAE/B,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\nconst DEVTOOLS_RTT_ADJUSTMENT_FACTOR = 3.75;\nconst DEVTOOLS_THROUGHPUT_ADJUSTMENT_FACTOR = 0.9;\n\nconst throttling = {\n DEVTOOLS_RTT_ADJUSTMENT_FACTOR,\n DEVTOOLS_THROUGHPUT_ADJUSTMENT_FACTOR,\n // These values align with WebPageTest's definition of \"Fast 3G\"\n // But offer similar characteristics to roughly the 75th percentile of 4G connections.\n mobileSlow4G: {\n rttMs: 150,\n throughputKbps: 1.6 * 1024,\n requestLatencyMs: 150 * DEVTOOLS_RTT_ADJUSTMENT_FACTOR,\n downloadThroughputKbps: 1.6 * 1024 * DEVTOOLS_THROUGHPUT_ADJUSTMENT_FACTOR,\n uploadThroughputKbps: 750 * DEVTOOLS_THROUGHPUT_ADJUSTMENT_FACTOR,\n cpuSlowdownMultiplier: 4,\n },\n // These values partially align with WebPageTest's definition of \"Regular 3G\".\n // These values are meant to roughly align with Chrome UX report's 3G definition which are based\n // on HTTP RTT of 300-1400ms and downlink throughput of <700kbps.\n mobileRegular3G: {\n rttMs: 300,\n throughputKbps: 700,\n requestLatencyMs: 300 * DEVTOOLS_RTT_ADJUSTMENT_FACTOR,\n downloadThroughputKbps: 700 * DEVTOOLS_THROUGHPUT_ADJUSTMENT_FACTOR,\n uploadThroughputKbps: 700 * DEVTOOLS_THROUGHPUT_ADJUSTMENT_FACTOR,\n cpuSlowdownMultiplier: 4,\n },\n // Using a \"broadband\" connection type\n // Corresponds to \"Dense 4G 25th percentile\" in https://docs.google.com/document/d/1Ft1Bnq9-t4jK5egLSOc28IL4TvR-Tt0se_1faTA4KTY/edit#heading=h.bb7nfy2x9e5v\n desktopDense4G: {\n rttMs: 40,\n throughputKbps: 10 * 1024,\n cpuSlowdownMultiplier: 1,\n requestLatencyMs: 0, // 0 means unset\n downloadThroughputKbps: 0,\n uploadThroughputKbps: 0,\n },\n};\n\nconst Constants = {throttling};\n\nexport {Constants};\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type * as Lantern from '../types/types.js';
|
|
2
|
+
declare class DNSCache {
|
|
3
|
+
static rttMultiplier: number;
|
|
4
|
+
_rtt: number;
|
|
5
|
+
_resolvedDomainNames: Map<string, {
|
|
6
|
+
resolvedAt: number;
|
|
7
|
+
}>;
|
|
8
|
+
constructor({ rtt }: {
|
|
9
|
+
rtt: number;
|
|
10
|
+
});
|
|
11
|
+
getTimeUntilResolution(request: Lantern.NetworkRequest, options?: {
|
|
12
|
+
requestedAt: number;
|
|
13
|
+
shouldUpdateCache: boolean;
|
|
14
|
+
}): number;
|
|
15
|
+
_updateCacheResolvedAtIfNeeded(request: Lantern.NetworkRequest, resolvedAt: number): void;
|
|
16
|
+
/**
|
|
17
|
+
* Forcefully sets the DNS resolution time for a request.
|
|
18
|
+
* Useful for testing and alternate execution simulations.
|
|
19
|
+
*/
|
|
20
|
+
setResolvedAt(domain: string, resolvedAt: number): void;
|
|
21
|
+
}
|
|
22
|
+
export { DNSCache };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Copyright 2024 The Chromium Authors. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
// A DNS lookup will usually take ~1-2 roundtrips of connection latency plus the extra DNS routing time.
|
|
5
|
+
// Example: https://www.webpagetest.org/result/180703_3A_e33ec79747c002ed4d7bcbfc81462203/1/details/#waterfall_view_step1
|
|
6
|
+
// Example: https://www.webpagetest.org/result/180707_1M_89673eb633b5d98386de95dfcf9b33d5/1/details/#waterfall_view_step1
|
|
7
|
+
// DNS is highly variable though, many times it's a little more than 1, but can easily be 4-5x RTT.
|
|
8
|
+
// We'll use 2 since it seems to give the most accurate results on average, but this can be tweaked.
|
|
9
|
+
const DNS_RESOLUTION_RTT_MULTIPLIER = 2;
|
|
10
|
+
class DNSCache {
|
|
11
|
+
static rttMultiplier = DNS_RESOLUTION_RTT_MULTIPLIER;
|
|
12
|
+
_rtt;
|
|
13
|
+
_resolvedDomainNames;
|
|
14
|
+
constructor({ rtt }) {
|
|
15
|
+
this._rtt = rtt;
|
|
16
|
+
this._resolvedDomainNames = new Map();
|
|
17
|
+
}
|
|
18
|
+
getTimeUntilResolution(request, options) {
|
|
19
|
+
const { requestedAt = 0, shouldUpdateCache = false } = options || {};
|
|
20
|
+
const domain = request.parsedURL.host;
|
|
21
|
+
const cacheEntry = this._resolvedDomainNames.get(domain);
|
|
22
|
+
let timeUntilResolved = this._rtt * DNSCache.rttMultiplier;
|
|
23
|
+
if (cacheEntry) {
|
|
24
|
+
const timeUntilCachedIsResolved = Math.max(cacheEntry.resolvedAt - requestedAt, 0);
|
|
25
|
+
timeUntilResolved = Math.min(timeUntilCachedIsResolved, timeUntilResolved);
|
|
26
|
+
}
|
|
27
|
+
const resolvedAt = requestedAt + timeUntilResolved;
|
|
28
|
+
if (shouldUpdateCache) {
|
|
29
|
+
this._updateCacheResolvedAtIfNeeded(request, resolvedAt);
|
|
30
|
+
}
|
|
31
|
+
return timeUntilResolved;
|
|
32
|
+
}
|
|
33
|
+
_updateCacheResolvedAtIfNeeded(request, resolvedAt) {
|
|
34
|
+
const domain = request.parsedURL.host;
|
|
35
|
+
const cacheEntry = this._resolvedDomainNames.get(domain) || { resolvedAt };
|
|
36
|
+
cacheEntry.resolvedAt = Math.min(cacheEntry.resolvedAt, resolvedAt);
|
|
37
|
+
this._resolvedDomainNames.set(domain, cacheEntry);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Forcefully sets the DNS resolution time for a request.
|
|
41
|
+
* Useful for testing and alternate execution simulations.
|
|
42
|
+
*/
|
|
43
|
+
setResolvedAt(domain, resolvedAt) {
|
|
44
|
+
this._resolvedDomainNames.set(domain, { resolvedAt });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export { DNSCache };
|
|
48
|
+
//# sourceMappingURL=DNSCache.js.map
|
|
@@ -0,0 +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/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"]}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type * as Lantern from '../types/lantern.js';
|
|
2
|
+
interface Summary {
|
|
3
|
+
min: number;
|
|
4
|
+
max: number;
|
|
5
|
+
avg: number;
|
|
6
|
+
median: number;
|
|
7
|
+
}
|
|
8
|
+
interface RTTEstimateOptions {
|
|
9
|
+
/**
|
|
10
|
+
* TCP connection handshake information will be used when available, but in
|
|
11
|
+
* some circumstances this data can be unreliable. This flag exposes an
|
|
12
|
+
* option to ignore the handshake data and use the coarse download/TTFB timing data.
|
|
13
|
+
*/
|
|
14
|
+
forceCoarseEstimates?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Coarse estimates include lots of extra time and noise multiply by some factor
|
|
17
|
+
* to deflate the estimates a bit.
|
|
18
|
+
*/
|
|
19
|
+
coarseEstimateMultiplier?: number;
|
|
20
|
+
/** Useful for testing to isolate the different methods of estimation. */
|
|
21
|
+
useDownloadEstimates?: boolean;
|
|
22
|
+
/** Useful for testing to isolate the different methods of estimation. */
|
|
23
|
+
useSendStartEstimates?: boolean;
|
|
24
|
+
/** Useful for testing to isolate the different methods of estimation. */
|
|
25
|
+
useHeadersEndEstimates?: boolean;
|
|
26
|
+
}
|
|
27
|
+
type RequestInfo = {
|
|
28
|
+
request: Lantern.NetworkRequest;
|
|
29
|
+
timing: Lantern.ResourceTiming;
|
|
30
|
+
connectionReused?: boolean;
|
|
31
|
+
};
|
|
32
|
+
declare class NetworkAnalyzer {
|
|
33
|
+
static get summary(): string;
|
|
34
|
+
static groupByOrigin(records: Lantern.NetworkRequest[]): Map<string, Lantern.NetworkRequest[]>;
|
|
35
|
+
static getSummary(values: number[]): Summary;
|
|
36
|
+
static summarize(values: Map<string, number[]>): Map<string, Summary>;
|
|
37
|
+
static _estimateValueByOrigin(requests: Lantern.NetworkRequest[], iteratee: (e: RequestInfo) => number | number[] | undefined): Map<string, number[]>;
|
|
38
|
+
/**
|
|
39
|
+
* Estimates the observed RTT to each origin based on how long the connection setup.
|
|
40
|
+
* For h1 and h2, this could includes two estimates - one for the TCP handshake, another for
|
|
41
|
+
* SSL negotiation.
|
|
42
|
+
* For h3, we get only one estimate since QUIC establishes a secure connection in a
|
|
43
|
+
* single handshake.
|
|
44
|
+
* This is the most accurate and preferred method of measurement when the data is available.
|
|
45
|
+
*/
|
|
46
|
+
static _estimateRTTViaConnectionTiming(info: RequestInfo): number[] | number | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* Estimates the observed RTT to each origin based on how long a download took on a fresh connection.
|
|
49
|
+
* NOTE: this will tend to overestimate the actual RTT quite significantly as the download can be
|
|
50
|
+
* slow for other reasons as well such as bandwidth constraints.
|
|
51
|
+
*/
|
|
52
|
+
static _estimateRTTViaDownloadTiming(info: RequestInfo): number | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* Estimates the observed RTT to each origin based on how long it took until Chrome could
|
|
55
|
+
* start sending the actual request when a new connection was required.
|
|
56
|
+
* NOTE: this will tend to overestimate the actual RTT as the request can be delayed for other
|
|
57
|
+
* reasons as well such as more SSL handshakes if TLS False Start is not enabled.
|
|
58
|
+
*/
|
|
59
|
+
static _estimateRTTViaSendStartTiming(info: RequestInfo): number | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* Estimates the observed RTT to each origin based on how long it took until Chrome received the
|
|
62
|
+
* headers of the response (~TTFB).
|
|
63
|
+
* NOTE: this is the most inaccurate way to estimate the RTT, but in some environments it's all
|
|
64
|
+
* we have access to :(
|
|
65
|
+
*/
|
|
66
|
+
static _estimateRTTViaHeadersEndTiming(info: RequestInfo): number | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Given the RTT to each origin, estimates the observed server response times.
|
|
69
|
+
*/
|
|
70
|
+
static _estimateResponseTimeByOrigin(records: Lantern.NetworkRequest[], rttByOrigin: Map<string, number>): Map<string, number[]>;
|
|
71
|
+
static canTrustConnectionInformation(requests: Lantern.NetworkRequest[]): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Returns a map of requestId -> connectionReused, estimating the information if the information
|
|
74
|
+
* available in the records themselves appears untrustworthy.
|
|
75
|
+
*/
|
|
76
|
+
static estimateIfConnectionWasReused(records: Lantern.NetworkRequest[], options?: {
|
|
77
|
+
forceCoarseEstimates: boolean;
|
|
78
|
+
}): Map<string, boolean>;
|
|
79
|
+
/**
|
|
80
|
+
* Estimates the RTT to each origin by examining observed network timing information.
|
|
81
|
+
* Attempts to use the most accurate information first and falls back to coarser estimates when it
|
|
82
|
+
* is unavailable.
|
|
83
|
+
*/
|
|
84
|
+
static estimateRTTByOrigin(records: Lantern.NetworkRequest[], options?: RTTEstimateOptions): Map<string, Summary>;
|
|
85
|
+
/**
|
|
86
|
+
* Estimates the server response time of each origin. RTT times can be passed in or will be
|
|
87
|
+
* estimated automatically if not provided.
|
|
88
|
+
*/
|
|
89
|
+
static estimateServerResponseTimeByOrigin(records: Lantern.NetworkRequest[], options?: RTTEstimateOptions & {
|
|
90
|
+
rttByOrigin?: Map<string, number>;
|
|
91
|
+
}): Map<string, Summary>;
|
|
92
|
+
/**
|
|
93
|
+
* Computes the average throughput for the given requests in bits/second.
|
|
94
|
+
* Excludes data URI, failed or otherwise incomplete, and cached requests.
|
|
95
|
+
* Returns Infinity if there were no analyzable network requests.
|
|
96
|
+
*/
|
|
97
|
+
static estimateThroughput(records: Lantern.NetworkRequest[]): number;
|
|
98
|
+
static computeRTTAndServerResponseTime(records: Lantern.NetworkRequest[]): {
|
|
99
|
+
rtt: number;
|
|
100
|
+
additionalRttByOrigin: Map<string, number>;
|
|
101
|
+
serverResponseTimeByOrigin: Map<string, number>;
|
|
102
|
+
};
|
|
103
|
+
static analyze(records: Lantern.NetworkRequest[]): Lantern.Simulation.Settings['networkAnalysis'];
|
|
104
|
+
static findResourceForUrl<T extends Lantern.NetworkRequest>(records: Array<T>, resourceUrl: string): T | undefined;
|
|
105
|
+
static findLastDocumentForUrl<T extends Lantern.NetworkRequest>(records: Array<T>, resourceUrl: string): T | undefined;
|
|
106
|
+
/**
|
|
107
|
+
* Resolves redirect chain given a main document.
|
|
108
|
+
* See: {@link NetworkAnalyzer.findLastDocumentForUrl} for how to retrieve main document.
|
|
109
|
+
*/
|
|
110
|
+
static resolveRedirects<T extends Lantern.NetworkRequest>(request: T): T;
|
|
111
|
+
}
|
|
112
|
+
export { NetworkAnalyzer };
|