@paulirish/trace_engine 0.0.28 → 0.0.29
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/SetUtilities.d.ts +0 -1
- package/core/platform/SetUtilities.js +0 -14
- package/core/platform/SetUtilities.js.map +1 -1
- package/generated/protocol.d.ts +61 -6
- package/models/trace/LanternComputationData.js +4 -4
- package/models/trace/LanternComputationData.js.map +1 -1
- package/models/trace/ModelImpl.d.ts +23 -23
- package/models/trace/ModelImpl.js +20 -12
- package/models/trace/ModelImpl.js.map +1 -1
- package/models/trace/Processor.d.ts +6 -7
- package/models/trace/Processor.js +102 -29
- package/models/trace/Processor.js.map +1 -1
- package/models/trace/extras/URLForEntry.js +1 -1
- package/models/trace/extras/URLForEntry.js.map +1 -1
- package/models/trace/handlers/ExtensionTraceDataHandler.js +2 -6
- package/models/trace/handlers/ExtensionTraceDataHandler.js.map +1 -1
- package/models/trace/handlers/InvalidationsHandler.d.ts +1 -1
- package/models/trace/handlers/InvalidationsHandler.js +2 -21
- package/models/trace/handlers/InvalidationsHandler.js.map +1 -1
- package/models/trace/handlers/LayoutShiftsHandler.d.ts +1 -0
- package/models/trace/handlers/LayoutShiftsHandler.js +5 -0
- package/models/trace/handlers/LayoutShiftsHandler.js.map +1 -1
- package/models/trace/handlers/NetworkRequestsHandler.d.ts +15 -0
- package/models/trace/handlers/NetworkRequestsHandler.js +98 -2
- package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -1
- package/models/trace/handlers/types.d.ts +1 -8
- package/models/trace/handlers/types.js +1 -17
- package/models/trace/handlers/types.js.map +1 -1
- package/models/trace/helpers/Extensions.d.ts +1 -1
- package/models/trace/helpers/Extensions.js +22 -8
- package/models/trace/helpers/Extensions.js.map +1 -1
- package/models/trace/helpers/Network.d.ts +2 -0
- package/models/trace/helpers/Network.js +7 -0
- package/models/trace/helpers/Network.js.map +1 -0
- package/models/trace/helpers/SyntheticEvents.d.ts +3 -8
- package/models/trace/helpers/SyntheticEvents.js +16 -25
- package/models/trace/helpers/SyntheticEvents.js.map +1 -1
- package/models/trace/helpers/Timing.d.ts +1 -0
- package/models/trace/helpers/Timing.js +3 -0
- package/models/trace/helpers/Timing.js.map +1 -1
- package/models/trace/helpers/Trace.d.ts +2 -0
- package/models/trace/helpers/Trace.js +3 -3
- package/models/trace/helpers/Trace.js.map +1 -1
- package/models/trace/helpers/helpers-tsconfig.json +1 -0
- package/models/trace/helpers/helpers.d.ts +1 -0
- package/models/trace/helpers/helpers.js +1 -0
- package/models/trace/helpers/helpers.js.map +1 -1
- package/models/trace/insights/LargestContentfulPaint.d.ts +2 -8
- package/models/trace/insights/LargestContentfulPaint.js +9 -5
- package/models/trace/insights/LargestContentfulPaint.js.map +1 -1
- package/models/trace/insights/RenderBlocking.d.ts +4 -2
- package/models/trace/insights/RenderBlocking.js +76 -1
- package/models/trace/insights/RenderBlocking.js.map +1 -1
- package/models/trace/insights/insights-tsconfig.json +3 -0
- package/models/trace/insights/types.d.ts +27 -19
- package/models/trace/insights/types.js.map +1 -1
- package/models/trace/lantern/core/NetworkAnalyzer.js +2 -1
- package/models/trace/lantern/core/NetworkAnalyzer.js.map +1 -1
- package/models/trace/lantern/graph/BaseNode.d.ts +5 -1
- package/models/trace/lantern/graph/BaseNode.js +11 -6
- package/models/trace/lantern/graph/BaseNode.js.map +1 -1
- package/models/trace/lantern/graph/PageDependencyGraph.js +8 -8
- package/models/trace/lantern/graph/PageDependencyGraph.js.map +1 -1
- package/models/trace/lantern/metrics/Interactive.d.ts +1 -1
- package/models/trace/lantern/metrics/Interactive.js +5 -4
- package/models/trace/lantern/metrics/Interactive.js.map +1 -1
- package/models/trace/lantern/metrics/LargestContentfulPaint.d.ts +1 -1
- package/models/trace/lantern/metrics/LargestContentfulPaint.js +3 -3
- package/models/trace/lantern/metrics/LargestContentfulPaint.js.map +1 -1
- package/models/trace/lantern/metrics/MaxPotentialFID.d.ts +1 -1
- package/models/trace/lantern/metrics/MaxPotentialFID.js +3 -2
- package/models/trace/lantern/metrics/MaxPotentialFID.js.map +1 -1
- package/models/trace/lantern/metrics/Metric.d.ts +1 -1
- package/models/trace/lantern/metrics/Metric.js +5 -4
- package/models/trace/lantern/metrics/Metric.js.map +1 -1
- package/models/trace/lantern/metrics/SpeedIndex.d.ts +1 -1
- package/models/trace/lantern/metrics/SpeedIndex.js +6 -5
- package/models/trace/lantern/metrics/SpeedIndex.js.map +1 -1
- package/models/trace/lantern/metrics/TotalBlockingTime.d.ts +1 -1
- package/models/trace/lantern/metrics/TotalBlockingTime.js +6 -5
- package/models/trace/lantern/metrics/TotalBlockingTime.js.map +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/SimulationTimingMap.d.ts +0 -7
- package/models/trace/lantern/simulation/SimulationTimingMap.js +15 -14
- package/models/trace/lantern/simulation/SimulationTimingMap.js.map +1 -1
- package/models/trace/lantern/simulation/Simulator.js +10 -9
- package/models/trace/lantern/simulation/Simulator.js.map +1 -1
- package/models/trace/lantern/simulation/simulation-tsconfig.json +3 -0
- package/models/trace/lantern/types/Lantern.d.ts +1 -1
- package/models/trace/lantern/types/Lantern.js.map +1 -1
- package/models/trace/types/Extensions.d.ts +29 -34
- package/models/trace/types/Extensions.js +7 -3
- package/models/trace/types/Extensions.js.map +1 -1
- package/models/trace/types/File.d.ts +16 -0
- package/models/trace/types/File.js.map +1 -1
- package/models/trace/types/TraceEvents.d.ts +31 -13
- package/models/trace/types/TraceEvents.js +14 -3
- package/models/trace/types/TraceEvents.js.map +1 -1
- package/package.json +1 -1
- package/models/trace/lantern/BaseNode.d.ts +0 -91
- package/models/trace/lantern/BaseNode.js +0 -268
- package/models/trace/lantern/BaseNode.js.map +0 -1
- package/models/trace/lantern/CPUNode.d.ts +0 -24
- package/models/trace/lantern/CPUNode.js +0 -64
- package/models/trace/lantern/CPUNode.js.map +0 -1
- package/models/trace/lantern/LanternError.d.ts +0 -3
- package/models/trace/lantern/LanternError.js +0 -7
- package/models/trace/lantern/LanternError.js.map +0 -1
- package/models/trace/lantern/MetricsModule.d.ts +0 -11
- package/models/trace/lantern/MetricsModule.js +0 -14
- package/models/trace/lantern/MetricsModule.js.map +0 -1
- package/models/trace/lantern/NetworkNode.d.ts +0 -22
- package/models/trace/lantern/NetworkNode.js +0 -83
- package/models/trace/lantern/NetworkNode.js.map +0 -1
- package/models/trace/lantern/PageDependencyGraph.d.ts +0 -43
- package/models/trace/lantern/PageDependencyGraph.js +0 -509
- package/models/trace/lantern/PageDependencyGraph.js.map +0 -1
- package/models/trace/lantern/SimulationModule.d.ts +0 -17
- package/models/trace/lantern/SimulationModule.js +0 -13
- package/models/trace/lantern/SimulationModule.js.map +0 -1
- package/models/trace/lantern/simulation/NetworkAnalyzer.d.ts +0 -112
- package/models/trace/lantern/simulation/NetworkAnalyzer.js +0 -486
- package/models/trace/lantern/simulation/NetworkAnalyzer.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Metric.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/metrics/Metric.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAiC3C,MAAM,MAAM;IACV,MAAM,CAAC,aAAa,CAAC,eAA2B,EAAE,yBAAgE;QAEhH,MAAM,UAAU,GAAgB,IAAI,GAAG,EAAE,CAAC;QAE1C,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;YAC9B,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;gBAC/C,OAAO;YACT,CAAC;YACD,IAAI,IAAI,CAAC,OAAO,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;gBAC3C,OAAO;YACT,CAAC;YACD,IAAI,yBAAyB,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACnC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,MAAM,KAAK,YAAY;QACrB,MAAM,IAAI,
|
|
1
|
+
{"version":3,"file":"Metric.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/metrics/Metric.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Core from '../core/core.js';\nimport * as Graph from '../graph/graph.js';\nimport type * as Simulation from '../simulation/simulation.js';\nimport type * as Types from '../types/types.js';\n\nexport interface MetricComputationDataInput {\n simulator: Simulation.Simulator;\n graph: Graph.Node<unknown>;\n processedNavigation: Types.Simulation.ProcessedNavigation;\n}\n\nexport interface MetricCoefficients {\n intercept: number;\n optimistic: number;\n pessimistic: number;\n}\n\nexport interface MetricResult<T = Types.AnyNetworkObject> {\n timing: number;\n timestamp?: never;\n optimisticEstimate: Simulation.Result<T>;\n pessimisticEstimate: Simulation.Result<T>;\n optimisticGraph: Graph.Node<T>;\n pessimisticGraph: Graph.Node;\n}\n\nexport interface Extras {\n optimistic: boolean;\n fcpResult?: MetricResult;\n lcpResult?: MetricResult;\n interactiveResult?: MetricResult;\n observedSpeedIndex?: number;\n}\n\nclass Metric {\n static getScriptUrls(dependencyGraph: Graph.Node, treatNodeAsRenderBlocking?: (node: Graph.NetworkNode) => boolean):\n Set<string> {\n const scriptUrls: Set<string> = new Set();\n\n dependencyGraph.traverse(node => {\n if (node.type !== Graph.BaseNode.types.NETWORK) {\n return;\n }\n if (node.request.resourceType !== 'Script') {\n return;\n }\n if (treatNodeAsRenderBlocking?.(node)) {\n scriptUrls.add(node.request.url);\n }\n });\n\n return scriptUrls;\n }\n\n static get coefficients(): MetricCoefficients {\n throw new Core.LanternError('coefficients unimplemented!');\n }\n\n /* eslint-disable @typescript-eslint/no-unused-vars */\n\n /**\n * Returns the coefficients, scaled by the throttling settings if needed by the metric.\n * Some lantern metrics (speed-index) use components in their estimate that are not\n * from the simulator. In this case, we need to adjust the coefficients as the target throttling\n * settings change.\n */\n static getScaledCoefficients(rttMs: number): MetricCoefficients {\n return this.coefficients;\n }\n\n static getOptimisticGraph(dependencyGraph: Graph.Node, processedNavigation: Types.Simulation.ProcessedNavigation):\n Graph.Node {\n throw new Core.LanternError('Optimistic graph unimplemented!');\n }\n\n static getPessimisticGraph(dependencyGraph: Graph.Node, processedNavigation: Types.Simulation.ProcessedNavigation):\n Graph.Node {\n throw new Core.LanternError('Pessmistic graph unimplemented!');\n }\n\n static getEstimateFromSimulation(simulationResult: Simulation.Result, extras: Extras): Simulation.Result {\n return simulationResult;\n }\n\n /* eslint-enable @typescript-eslint/no-unused-vars */\n\n static compute(data: MetricComputationDataInput, extras?: Omit<Extras, 'optimistic'>): MetricResult {\n const {simulator, graph, processedNavigation} = data;\n\n const metricName = this.name.replace('Lantern', '');\n const optimisticGraph = this.getOptimisticGraph(graph, processedNavigation);\n const pessimisticGraph = this.getPessimisticGraph(graph, processedNavigation);\n\n let simulateOptions = {label: `optimistic${metricName}`};\n const optimisticSimulation = simulator.simulate(optimisticGraph, simulateOptions);\n\n simulateOptions = {label: `pessimistic${metricName}`};\n const pessimisticSimulation = simulator.simulate(pessimisticGraph, simulateOptions);\n\n const optimisticEstimate = this.getEstimateFromSimulation(\n optimisticSimulation,\n {...extras, optimistic: true},\n );\n\n const pessimisticEstimate = this.getEstimateFromSimulation(\n pessimisticSimulation,\n {...extras, optimistic: false},\n );\n\n const coefficients = this.getScaledCoefficients(simulator.rtt);\n // Estimates under 1s don't really follow the normal curve fit, minimize the impact of the intercept\n const interceptMultiplier = coefficients.intercept > 0 ? Math.min(1, optimisticEstimate.timeInMs / 1000) : 1;\n const timing = coefficients.intercept * interceptMultiplier +\n coefficients.optimistic * optimisticEstimate.timeInMs + coefficients.pessimistic * pessimisticEstimate.timeInMs;\n\n return {\n timing,\n optimisticEstimate,\n pessimisticEstimate,\n optimisticGraph,\n pessimisticGraph,\n };\n }\n}\n\nexport {Metric};\n"]}
|
|
@@ -7,7 +7,7 @@ declare class SpeedIndex extends Metric {
|
|
|
7
7
|
static getOptimisticGraph(dependencyGraph: Graph.Node): Graph.Node;
|
|
8
8
|
static getPessimisticGraph(dependencyGraph: Graph.Node): Graph.Node;
|
|
9
9
|
static getEstimateFromSimulation(simulationResult: Simulation.Result, extras: Extras): Simulation.Result;
|
|
10
|
-
static compute(data: MetricComputationDataInput, extras?: Omit<Extras, 'optimistic'>):
|
|
10
|
+
static compute(data: MetricComputationDataInput, extras?: Omit<Extras, 'optimistic'>): MetricResult;
|
|
11
11
|
/**
|
|
12
12
|
* Approximate speed index using layout events from the simulated node timings.
|
|
13
13
|
* The layout-based speed index is the weighted average of the endTime of CPU nodes that contained
|
|
@@ -1,6 +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 * as Core from '../core/core.js';
|
|
4
5
|
import * as Graph from '../graph/graph.js';
|
|
5
6
|
import { Metric, } from './Metric.js';
|
|
6
7
|
const mobileSlow4GRtt = 150;
|
|
@@ -43,10 +44,10 @@ class SpeedIndex extends Metric {
|
|
|
43
44
|
}
|
|
44
45
|
static getEstimateFromSimulation(simulationResult, extras) {
|
|
45
46
|
if (!extras.fcpResult) {
|
|
46
|
-
throw new
|
|
47
|
+
throw new Core.LanternError('missing fcpResult');
|
|
47
48
|
}
|
|
48
49
|
if (extras.observedSpeedIndex === undefined) {
|
|
49
|
-
throw new
|
|
50
|
+
throw new Core.LanternError('missing observedSpeedIndex');
|
|
50
51
|
}
|
|
51
52
|
const fcpTimeInMs = extras.fcpResult.pessimisticEstimate.timeInMs;
|
|
52
53
|
const estimate = extras.optimistic ?
|
|
@@ -57,12 +58,12 @@ class SpeedIndex extends Metric {
|
|
|
57
58
|
nodeTimings: simulationResult.nodeTimings,
|
|
58
59
|
};
|
|
59
60
|
}
|
|
60
|
-
static
|
|
61
|
+
static compute(data, extras) {
|
|
61
62
|
const fcpResult = extras?.fcpResult;
|
|
62
63
|
if (!fcpResult) {
|
|
63
|
-
throw new
|
|
64
|
+
throw new Core.LanternError('FCP is required to calculate the SpeedIndex metric');
|
|
64
65
|
}
|
|
65
|
-
const metricResult =
|
|
66
|
+
const metricResult = super.compute(data, extras);
|
|
66
67
|
metricResult.timing = Math.max(metricResult.timing, fcpResult.timing);
|
|
67
68
|
return metricResult;
|
|
68
69
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpeedIndex.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/metrics/SpeedIndex.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAG3C,OAAO,EAEL,MAAM,GAIP,MAAM,aAAa,CAAC;AAErB,MAAM,eAAe,GAAG,GAAG,CAAC;AAE5B,MAAM,UAAW,SAAQ,MAAM;IAC7B,MAAM,KAAc,YAAY;QAC9B,OAAO;YACL,4FAA4F;YAC5F,kFAAkF;YAClF,SAAS,EAAE,CAAC;YACZ,UAAU,EAAE,GAAG;YACf,WAAW,EAAE,GAAG;SACjB,CAAC;IACJ,CAAC;IAED,MAAM,CAAU,qBAAqB,CAAC,KAAa;QACjD,kFAAkF;QAClF,wGAAwG;QACxG,yGAAyG;QACzG,uEAAuE;QACvE,gGAAgG;QAChG,8FAA8F;QAC9F,qCAAqC;QACrC,sHAAsH;QACtH,gGAAgG;QAChG,gFAAgF;QAChF,yGAAyG;QACzG,MAAM,mBAAmB,GAAG,IAAI,CAAC,YAAY,CAAC;QAC9C,MAAM,gBAAgB,GAAG,eAAe,GAAG,EAAE,CAAC;QAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,gBAAgB,EAAE,CAAC,CAAC,CAAC;QAEhE,OAAO;YACL,SAAS,EAAE,mBAAmB,CAAC,SAAS,GAAG,UAAU;YACrD,UAAU,EAAE,GAAG,GAAG,CAAC,mBAAmB,CAAC,UAAU,GAAG,GAAG,CAAC,GAAG,UAAU;YACrE,WAAW,EAAE,GAAG,GAAG,CAAC,mBAAmB,CAAC,WAAW,GAAG,GAAG,CAAC,GAAG,UAAU;SACxE,CAAC;IACJ,CAAC;IAED,MAAM,CAAU,kBAAkB,CAAC,eAA2B;QAC5D,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,MAAM,CAAU,mBAAmB,CAAC,eAA2B;QAC7D,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,MAAM,CAAU,yBAAyB,CAAC,gBAAmC,EAAE,MAAc;QAC3F,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;YACtB,MAAM,IAAI,
|
|
1
|
+
{"version":3,"file":"SpeedIndex.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/metrics/SpeedIndex.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Core from '../core/core.js';\nimport * as Graph from '../graph/graph.js';\nimport type * as Simulation from '../simulation/simulation.js';\n\nimport {\n type Extras,\n Metric,\n type MetricCoefficients,\n type MetricComputationDataInput,\n type MetricResult,\n} from './Metric.js';\n\nconst mobileSlow4GRtt = 150;\n\nclass SpeedIndex extends Metric {\n static override get coefficients(): MetricCoefficients {\n return {\n // Note that the optimistic estimate is based on the real observed speed index rather than a\n // real lantern graph (and the final estimate will be Math.max(FCP, Speed Index)).\n intercept: 0,\n optimistic: 1.4,\n pessimistic: 0.4,\n };\n }\n\n static override getScaledCoefficients(rttMs: number): MetricCoefficients {\n // We want to scale our default coefficients based on the speed of the connection.\n // We will linearly interpolate coefficients for the passed-in rttMs based on two pre-determined points:\n // 1. Baseline point of 30 ms RTT where Speed Index should be a ~50/50 blend of optimistic/pessimistic.\n // 30 ms was based on a typical home WiFi connection's actual RTT.\n // Coefficients here follow from the fact that the optimistic estimate should be very close\n // to reality at this connection speed and the pessimistic estimate compensates for minor\n // connection speed differences.\n // 2. Default throttled point of 150 ms RTT where the default coefficients have been determined to be most accurate.\n // Coefficients here were determined through thorough analysis and linear regression on the\n // lantern test data set. See core/scripts/test-lantern.sh for more detail.\n // While the coefficients haven't been analyzed at the interpolated points, it's our current best effort.\n const defaultCoefficients = this.coefficients;\n const defaultRttExcess = mobileSlow4GRtt - 30;\n const multiplier = Math.max((rttMs - 30) / defaultRttExcess, 0);\n\n return {\n intercept: defaultCoefficients.intercept * multiplier,\n optimistic: 0.5 + (defaultCoefficients.optimistic - 0.5) * multiplier,\n pessimistic: 0.5 + (defaultCoefficients.pessimistic - 0.5) * multiplier,\n };\n }\n\n static override getOptimisticGraph(dependencyGraph: Graph.Node): Graph.Node {\n return dependencyGraph;\n }\n\n static override getPessimisticGraph(dependencyGraph: Graph.Node): Graph.Node {\n return dependencyGraph;\n }\n\n static override getEstimateFromSimulation(simulationResult: Simulation.Result, extras: Extras): Simulation.Result {\n if (!extras.fcpResult) {\n throw new Core.LanternError('missing fcpResult');\n }\n if (extras.observedSpeedIndex === undefined) {\n throw new Core.LanternError('missing observedSpeedIndex');\n }\n\n const fcpTimeInMs = extras.fcpResult.pessimisticEstimate.timeInMs;\n const estimate = extras.optimistic ?\n extras.observedSpeedIndex :\n SpeedIndex.computeLayoutBasedSpeedIndex(simulationResult.nodeTimings, fcpTimeInMs);\n return {\n timeInMs: estimate,\n nodeTimings: simulationResult.nodeTimings,\n };\n }\n\n static override compute(data: MetricComputationDataInput, extras?: Omit<Extras, 'optimistic'>): MetricResult {\n const fcpResult = extras?.fcpResult;\n if (!fcpResult) {\n throw new Core.LanternError('FCP is required to calculate the SpeedIndex metric');\n }\n\n const metricResult = super.compute(data, extras);\n metricResult.timing = Math.max(metricResult.timing, fcpResult.timing);\n return metricResult;\n }\n\n /**\n * Approximate speed index using layout events from the simulated node timings.\n * The layout-based speed index is the weighted average of the endTime of CPU nodes that contained\n * a 'Layout' task. log(duration) is used as the weight to stand for \"significance\" to the page.\n *\n * If no layout events can be found or the endTime of a CPU task is too early, FCP is used instead.\n *\n * This approach was determined after evaluating the accuracy/complexity tradeoff of many\n * different methods. Read more in the evaluation doc.\n *\n * @see https://docs.google.com/document/d/1qJWXwxoyVLVadezIp_Tgdk867G3tDNkkVRvUJSH3K1E/edit#\n */\n static computeLayoutBasedSpeedIndex(nodeTimings: Simulation.Result['nodeTimings'], fcpTimeInMs: number): number {\n const layoutWeights: Array<{time: number, weight: number}> = [];\n for (const [node, timing] of nodeTimings.entries()) {\n if (node.type !== Graph.BaseNode.types.CPU) {\n continue;\n }\n\n if (node.childEvents.some(x => x.name === 'Layout')) {\n const timingWeight = Math.max(Math.log2(timing.endTime - timing.startTime), 0);\n layoutWeights.push({time: timing.endTime, weight: timingWeight});\n }\n }\n\n const totalWeightedTime =\n layoutWeights.map(evt => evt.weight * Math.max(evt.time, fcpTimeInMs)).reduce((a, b) => a + b, 0);\n const totalWeight = layoutWeights.map(evt => evt.weight).reduce((a, b) => a + b, 0);\n\n if (!totalWeight) {\n return fcpTimeInMs;\n }\n return totalWeightedTime / totalWeight;\n }\n}\n\nexport {SpeedIndex};\n"]}
|
|
@@ -6,7 +6,7 @@ declare class TotalBlockingTime extends Metric {
|
|
|
6
6
|
static getOptimisticGraph(dependencyGraph: Graph.Node): Graph.Node;
|
|
7
7
|
static getPessimisticGraph(dependencyGraph: Graph.Node): Graph.Node;
|
|
8
8
|
static getEstimateFromSimulation(simulation: Simulation.Result, extras: Extras): Simulation.Result;
|
|
9
|
-
static compute(data: MetricComputationDataInput, extras?: Omit<Extras, 'optimistic'>):
|
|
9
|
+
static compute(data: MetricComputationDataInput, extras?: Omit<Extras, 'optimistic'>): MetricResult;
|
|
10
10
|
static getTopLevelEvents(nodeTimings: Simulation.Result['nodeTimings'], minDurationMs: number): {
|
|
11
11
|
start: number;
|
|
12
12
|
end: number;
|
|
@@ -1,6 +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 * as Core from '../core/core.js';
|
|
4
5
|
import * as Graph from '../graph/graph.js';
|
|
5
6
|
import { Metric, } from './Metric.js';
|
|
6
7
|
import { BLOCKING_TIME_THRESHOLD, calculateSumOfBlockingTime } from './TBTUtils.js';
|
|
@@ -20,10 +21,10 @@ class TotalBlockingTime extends Metric {
|
|
|
20
21
|
}
|
|
21
22
|
static getEstimateFromSimulation(simulation, extras) {
|
|
22
23
|
if (!extras.fcpResult) {
|
|
23
|
-
throw new
|
|
24
|
+
throw new Core.LanternError('missing fcpResult');
|
|
24
25
|
}
|
|
25
26
|
if (!extras.interactiveResult) {
|
|
26
|
-
throw new
|
|
27
|
+
throw new Core.LanternError('missing interactiveResult');
|
|
27
28
|
}
|
|
28
29
|
// Intentionally use the opposite FCP estimate. A pessimistic FCP is higher than equal to an
|
|
29
30
|
// optimistic FCP, which means potentially more tasks are excluded from the Total Blocking Time
|
|
@@ -44,14 +45,14 @@ class TotalBlockingTime extends Metric {
|
|
|
44
45
|
nodeTimings: simulation.nodeTimings,
|
|
45
46
|
};
|
|
46
47
|
}
|
|
47
|
-
static
|
|
48
|
+
static compute(data, extras) {
|
|
48
49
|
const fcpResult = extras?.fcpResult;
|
|
49
50
|
if (!fcpResult) {
|
|
50
|
-
throw new
|
|
51
|
+
throw new Core.LanternError('FCP is required to calculate the TBT metric');
|
|
51
52
|
}
|
|
52
53
|
const interactiveResult = extras?.fcpResult;
|
|
53
54
|
if (!interactiveResult) {
|
|
54
|
-
throw new
|
|
55
|
+
throw new Core.LanternError('Interactive is required to calculate the TBT metric');
|
|
55
56
|
}
|
|
56
57
|
return super.compute(data, extras);
|
|
57
58
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TotalBlockingTime.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/metrics/TotalBlockingTime.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAG3C,OAAO,EAEL,MAAM,GAIP,MAAM,aAAa,CAAC;AACrB,OAAO,EAAC,uBAAuB,EAAE,0BAA0B,EAAC,MAAM,eAAe,CAAC;AAElF,MAAM,iBAAkB,SAAQ,MAAM;IACpC,MAAM,KAAc,YAAY;QAC9B,OAAO;YACL,SAAS,EAAE,CAAC;YACZ,UAAU,EAAE,GAAG;YACf,WAAW,EAAE,GAAG;SACjB,CAAC;IACJ,CAAC;IAED,MAAM,CAAU,kBAAkB,CAAC,eAA2B;QAC5D,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,MAAM,CAAU,mBAAmB,CAAC,eAA2B;QAC7D,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,MAAM,CAAU,yBAAyB,CAAC,UAA6B,EAAE,MAAc;QACrF,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;YACtB,MAAM,IAAI,
|
|
1
|
+
{"version":3,"file":"TotalBlockingTime.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/metrics/TotalBlockingTime.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Core from '../core/core.js';\nimport * as Graph from '../graph/graph.js';\nimport type * as Simulation from '../simulation/simulation.js';\n\nimport {\n type Extras,\n Metric,\n type MetricCoefficients,\n type MetricComputationDataInput,\n type MetricResult,\n} from './Metric.js';\nimport {BLOCKING_TIME_THRESHOLD, calculateSumOfBlockingTime} from './TBTUtils.js';\n\nclass TotalBlockingTime extends Metric {\n static override get coefficients(): MetricCoefficients {\n return {\n intercept: 0,\n optimistic: 0.5,\n pessimistic: 0.5,\n };\n }\n\n static override getOptimisticGraph(dependencyGraph: Graph.Node): Graph.Node {\n return dependencyGraph;\n }\n\n static override getPessimisticGraph(dependencyGraph: Graph.Node): Graph.Node {\n return dependencyGraph;\n }\n\n static override getEstimateFromSimulation(simulation: Simulation.Result, extras: Extras): Simulation.Result {\n if (!extras.fcpResult) {\n throw new Core.LanternError('missing fcpResult');\n }\n if (!extras.interactiveResult) {\n throw new Core.LanternError('missing interactiveResult');\n }\n\n // Intentionally use the opposite FCP estimate. A pessimistic FCP is higher than equal to an\n // optimistic FCP, which means potentially more tasks are excluded from the Total Blocking Time\n // computation. So a more pessimistic FCP gives a more optimistic Total Blocking Time for the\n // same work.\n const fcpTimeInMs = extras.optimistic ? extras.fcpResult.pessimisticEstimate.timeInMs :\n extras.fcpResult.optimisticEstimate.timeInMs;\n\n // Similarly, we always have pessimistic TTI >= optimistic TTI. Therefore, picking optimistic\n // TTI means our window of interest is smaller and thus potentially more tasks are excluded from\n // Total Blocking Time computation, yielding a lower (more optimistic) Total Blocking Time value\n // for the same work.\n const interactiveTimeMs = extras.optimistic ? extras.interactiveResult.optimisticEstimate.timeInMs :\n extras.interactiveResult.pessimisticEstimate.timeInMs;\n\n const minDurationMs = BLOCKING_TIME_THRESHOLD;\n\n const events = TotalBlockingTime.getTopLevelEvents(\n simulation.nodeTimings,\n minDurationMs,\n );\n\n return {\n timeInMs: calculateSumOfBlockingTime(\n events,\n fcpTimeInMs,\n interactiveTimeMs,\n ),\n nodeTimings: simulation.nodeTimings,\n };\n }\n\n static override compute(data: MetricComputationDataInput, extras?: Omit<Extras, 'optimistic'>): MetricResult {\n const fcpResult = extras?.fcpResult;\n if (!fcpResult) {\n throw new Core.LanternError('FCP is required to calculate the TBT metric');\n }\n\n const interactiveResult = extras?.fcpResult;\n if (!interactiveResult) {\n throw new Core.LanternError('Interactive is required to calculate the TBT metric');\n }\n\n return super.compute(data, extras);\n }\n\n static getTopLevelEvents(nodeTimings: Simulation.Result['nodeTimings'], minDurationMs: number):\n {start: number, end: number, duration: number}[] {\n const events: Array<{start: number, end: number, duration: number}> = [];\n\n for (const [node, timing] of nodeTimings.entries()) {\n if (node.type !== Graph.BaseNode.types.CPU) {\n continue;\n }\n // Filtering out events below minimum duration.\n if (timing.duration < minDurationMs) {\n continue;\n }\n\n events.push({\n start: timing.startTime,\n end: timing.endTime,\n duration: timing.duration,\n });\n }\n\n return events;\n }\n}\n\nexport {TotalBlockingTime};\n"]}
|
|
@@ -48,7 +48,7 @@ export class ConnectionPool {
|
|
|
48
48
|
connections.push(connection);
|
|
49
49
|
}
|
|
50
50
|
if (!connections.length) {
|
|
51
|
-
throw new
|
|
51
|
+
throw new Core.LanternError(`Could not find a connection for origin: ${origin}`);
|
|
52
52
|
}
|
|
53
53
|
// Make sure each origin has minimum number of connections available for max throughput.
|
|
54
54
|
// But only if it's not over H2 which maximizes throughput already.
|
|
@@ -82,7 +82,7 @@ export class ConnectionPool {
|
|
|
82
82
|
*/
|
|
83
83
|
acquire(request) {
|
|
84
84
|
if (this._connectionsByRequest.has(request)) {
|
|
85
|
-
throw new
|
|
85
|
+
throw new Core.LanternError('Record already has a connection');
|
|
86
86
|
}
|
|
87
87
|
const origin = request.parsedURL.securityOrigin;
|
|
88
88
|
const connections = this._connectionsByOrigin.get(origin) || [];
|
|
@@ -101,7 +101,7 @@ export class ConnectionPool {
|
|
|
101
101
|
acquireActiveConnectionFromRequest(request) {
|
|
102
102
|
const activeConnection = this._connectionsByRequest.get(request);
|
|
103
103
|
if (!activeConnection) {
|
|
104
|
-
throw new
|
|
104
|
+
throw new Core.LanternError('Could not find an active connection for request');
|
|
105
105
|
}
|
|
106
106
|
return activeConnection;
|
|
107
107
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConnectionPool.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/simulation/ConnectionPool.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAC;AAGxC,OAAO,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AAEjD,MAAM,4BAA4B,GAAG,EAAE,CAAC;AACxC,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AAErC,uDAAuD;AACvD,wHAAwH;AACxH,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAEjC,MAAM,OAAO,cAAc;IACzB,QAAQ,CAAuC;IAC/C,QAAQ,CAA2B;IACnC,oBAAoB,CAA+B;IACnD,qBAAqB,CAA6C;IAClE,iBAAiB,CAAqB;IACtC,4BAA4B,CAAuB;IAEnD,YAAY,OAAiC,EAAE,OAA6C;QAC1F,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QAExB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,CAAC,oBAAoB,GAAG,IAAI,GAAG,EAAE,CAAC;QACtC,IAAI,CAAC,qBAAqB,GAAG,IAAI,GAAG,EAAE,CAAC;QACvC,IAAI,CAAC,iBAAiB,GAAG,IAAI,GAAG,EAAE,CAAC;QACnC,IAAI,CAAC,4BAA4B,GAAG,IAAI,CAAC,eAAe,CAAC,6BAA6B,CAAC,OAAO,EAAE;YAC9F,oBAAoB,EAAE,IAAI;SAC3B,CAAC,CAAC;QAEH,IAAI,CAAC,sBAAsB,EAAE,CAAC;IAChC,CAAC;IAED,gBAAgB;QACd,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC5C,CAAC;IAED,sBAAsB;QACpB,MAAM,gBAAgB,GAAG,IAAI,CAAC,4BAA4B,CAAC;QAC3D,MAAM,qBAAqB,GAAG,IAAI,CAAC,QAAQ,CAAC,qBAAqB,CAAC;QAClE,MAAM,0BAA0B,GAAG,IAAI,CAAC,QAAQ,CAAC,0BAA0B,CAAC;QAE5E,MAAM,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC1E,KAAK,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,eAAe,CAAC,OAAO,EAAE,EAAE,CAAC;YAC3D,MAAM,WAAW,GAAG,EAAE,CAAC;YACvB,MAAM,aAAa,GAAG,qBAAqB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC7D,MAAM,YAAY,GAAG,0BAA0B,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,4BAA4B,CAAC;YAE5F,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAC/B,IAAI,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC5C,SAAS;gBACX,CAAC;gBAED,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;gBAC7D,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,KAAK,IAAI,CAAC;gBACvC,MAAM,UAAU,GAAG,IAAI,aAAa,CAChC,IAAI,CAAC,QAAQ,CAAC,GAAG,GAAG,aAAa,EACjC,IAAI,CAAC,QAAQ,CAAC,UAAU,EACxB,YAAY,EACZ,KAAK,EACL,IAAI,CACP,CAAC;gBAEF,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC/B,CAAC;YAED,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;gBACxB,MAAM,IAAI,
|
|
1
|
+
{"version":3,"file":"ConnectionPool.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/simulation/ConnectionPool.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAC;AAGxC,OAAO,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AAEjD,MAAM,4BAA4B,GAAG,EAAE,CAAC;AACxC,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AAErC,uDAAuD;AACvD,wHAAwH;AACxH,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAEjC,MAAM,OAAO,cAAc;IACzB,QAAQ,CAAuC;IAC/C,QAAQ,CAA2B;IACnC,oBAAoB,CAA+B;IACnD,qBAAqB,CAA6C;IAClE,iBAAiB,CAAqB;IACtC,4BAA4B,CAAuB;IAEnD,YAAY,OAAiC,EAAE,OAA6C;QAC1F,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QAExB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,CAAC,oBAAoB,GAAG,IAAI,GAAG,EAAE,CAAC;QACtC,IAAI,CAAC,qBAAqB,GAAG,IAAI,GAAG,EAAE,CAAC;QACvC,IAAI,CAAC,iBAAiB,GAAG,IAAI,GAAG,EAAE,CAAC;QACnC,IAAI,CAAC,4BAA4B,GAAG,IAAI,CAAC,eAAe,CAAC,6BAA6B,CAAC,OAAO,EAAE;YAC9F,oBAAoB,EAAE,IAAI;SAC3B,CAAC,CAAC;QAEH,IAAI,CAAC,sBAAsB,EAAE,CAAC;IAChC,CAAC;IAED,gBAAgB;QACd,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC5C,CAAC;IAED,sBAAsB;QACpB,MAAM,gBAAgB,GAAG,IAAI,CAAC,4BAA4B,CAAC;QAC3D,MAAM,qBAAqB,GAAG,IAAI,CAAC,QAAQ,CAAC,qBAAqB,CAAC;QAClE,MAAM,0BAA0B,GAAG,IAAI,CAAC,QAAQ,CAAC,0BAA0B,CAAC;QAE5E,MAAM,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC1E,KAAK,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,eAAe,CAAC,OAAO,EAAE,EAAE,CAAC;YAC3D,MAAM,WAAW,GAAG,EAAE,CAAC;YACvB,MAAM,aAAa,GAAG,qBAAqB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC7D,MAAM,YAAY,GAAG,0BAA0B,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,4BAA4B,CAAC;YAE5F,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAC/B,IAAI,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC5C,SAAS;gBACX,CAAC;gBAED,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;gBAC7D,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,KAAK,IAAI,CAAC;gBACvC,MAAM,UAAU,GAAG,IAAI,aAAa,CAChC,IAAI,CAAC,QAAQ,CAAC,GAAG,GAAG,aAAa,EACjC,IAAI,CAAC,QAAQ,CAAC,UAAU,EACxB,YAAY,EACZ,KAAK,EACL,IAAI,CACP,CAAC;gBAEF,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC/B,CAAC;YAED,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;gBACxB,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,2CAA2C,MAAM,EAAE,CAAC,CAAC;YACnF,CAAC;YAED,wFAAwF;YACxF,mEAAmE;YACnE,MAAM,cAAc,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC;YAC1E,OAAO,WAAW,CAAC,MAAM,GAAG,cAAc,EAAE,CAAC;gBAC3C,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;YAC3C,CAAC;YAED,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAED,mDAAmD,CAAC,WAA4B;QAC9E,IAAI,aAAa,GAAuB,IAAI,CAAC;QAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5C,MAAM,UAAU,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;YAElC,mDAAmD;YACnD,IAAI,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC3C,SAAS;YACX,CAAC;YAED,kGAAkG;YAClG,MAAM,UAAU,GAAG,CAAC,aAAa,EAAE,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC;YAClE,IAAI,UAAU,CAAC,gBAAgB,GAAG,UAAU,EAAE,CAAC;gBAC7C,aAAa,GAAG,UAAU,CAAC;YAC7B,CAAC;QACH,CAAC;QAED,OAAO,aAAa,CAAC;IACvB,CAAC;IAED;;;;OAIG;IACH,OAAO,CAAC,OAA+B;QACrC,IAAI,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5C,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,iCAAiC,CAAC,CAAC;QACjE,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,cAAc,CAAC;QAChD,MAAM,WAAW,GAAG,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAChE,MAAM,eAAe,GAAG,IAAI,CAAC,mDAAmD,CAAC,WAAW,CAAC,CAAC;QAE9F,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAC5C,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;QACzD,OAAO,eAAe,CAAC;IACzB,CAAC;IAED;;;OAGG;IACH,kCAAkC,CAAC,OAA+B;QAChE,MAAM,gBAAgB,GAAG,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACjE,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,iDAAiD,CAAC,CAAC;QACjF,CAAC;QAED,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,OAAO,CAAC,OAA+B;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC3D,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC3C,IAAI,UAAU,EAAE,CAAC;YACf,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;CACF","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 Core.LanternError(`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 Core.LanternError('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 Core.LanternError('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"]}
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview
|
|
3
|
-
*
|
|
4
|
-
* This class encapsulates the type-related validation logic for moving timing information for nodes
|
|
5
|
-
* through the different simulation phases. Methods here ensure that the invariants of simulation hold
|
|
6
|
-
* as nodes are queued, partially simulated, and completed.
|
|
7
|
-
*/
|
|
8
1
|
import * as Graph from '../graph/graph.js';
|
|
9
2
|
interface NodeTimingComplete {
|
|
10
3
|
startTime: number;
|
|
@@ -8,6 +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 * as Core from '../core/core.js';
|
|
11
12
|
import * as Graph from '../graph/graph.js';
|
|
12
13
|
class SimulatorTimingMap {
|
|
13
14
|
_nodeTimings;
|
|
@@ -70,62 +71,62 @@ class SimulatorTimingMap {
|
|
|
70
71
|
getQueued(node) {
|
|
71
72
|
const timing = this._nodeTimings.get(node);
|
|
72
73
|
if (!timing) {
|
|
73
|
-
throw new
|
|
74
|
+
throw new Core.LanternError(`Node ${node.id} not yet queued`);
|
|
74
75
|
}
|
|
75
76
|
return timing;
|
|
76
77
|
}
|
|
77
78
|
getCpuStarted(node) {
|
|
78
79
|
const timing = this._nodeTimings.get(node);
|
|
79
80
|
if (!timing) {
|
|
80
|
-
throw new
|
|
81
|
+
throw new Core.LanternError(`Node ${node.id} not yet queued`);
|
|
81
82
|
}
|
|
82
83
|
if (!('startTime' in timing)) {
|
|
83
|
-
throw new
|
|
84
|
+
throw new Core.LanternError(`Node ${node.id} not yet started`);
|
|
84
85
|
}
|
|
85
86
|
if ('bytesDownloaded' in timing) {
|
|
86
|
-
throw new
|
|
87
|
+
throw new Core.LanternError(`Node ${node.id} timing not valid`);
|
|
87
88
|
}
|
|
88
89
|
return timing;
|
|
89
90
|
}
|
|
90
91
|
getNetworkStarted(node) {
|
|
91
92
|
const timing = this._nodeTimings.get(node);
|
|
92
93
|
if (!timing) {
|
|
93
|
-
throw new
|
|
94
|
+
throw new Core.LanternError(`Node ${node.id} not yet queued`);
|
|
94
95
|
}
|
|
95
96
|
if (!('startTime' in timing)) {
|
|
96
|
-
throw new
|
|
97
|
+
throw new Core.LanternError(`Node ${node.id} not yet started`);
|
|
97
98
|
}
|
|
98
99
|
if (!('bytesDownloaded' in timing)) {
|
|
99
|
-
throw new
|
|
100
|
+
throw new Core.LanternError(`Node ${node.id} timing not valid`);
|
|
100
101
|
}
|
|
101
102
|
return timing;
|
|
102
103
|
}
|
|
103
104
|
getInProgress(node) {
|
|
104
105
|
const timing = this._nodeTimings.get(node);
|
|
105
106
|
if (!timing) {
|
|
106
|
-
throw new
|
|
107
|
+
throw new Core.LanternError(`Node ${node.id} not yet queued`);
|
|
107
108
|
}
|
|
108
109
|
if (!('startTime' in timing)) {
|
|
109
|
-
throw new
|
|
110
|
+
throw new Core.LanternError(`Node ${node.id} not yet started`);
|
|
110
111
|
}
|
|
111
112
|
if (!('estimatedTimeElapsed' in timing)) {
|
|
112
|
-
throw new
|
|
113
|
+
throw new Core.LanternError(`Node ${node.id} not yet in progress`);
|
|
113
114
|
}
|
|
114
115
|
return timing;
|
|
115
116
|
}
|
|
116
117
|
getCompleted(node) {
|
|
117
118
|
const timing = this._nodeTimings.get(node);
|
|
118
119
|
if (!timing) {
|
|
119
|
-
throw new
|
|
120
|
+
throw new Core.LanternError(`Node ${node.id} not yet queued`);
|
|
120
121
|
}
|
|
121
122
|
if (!('startTime' in timing)) {
|
|
122
|
-
throw new
|
|
123
|
+
throw new Core.LanternError(`Node ${node.id} not yet started`);
|
|
123
124
|
}
|
|
124
125
|
if (!('estimatedTimeElapsed' in timing)) {
|
|
125
|
-
throw new
|
|
126
|
+
throw new Core.LanternError(`Node ${node.id} not yet in progress`);
|
|
126
127
|
}
|
|
127
128
|
if (!('endTime' in timing)) {
|
|
128
|
-
throw new
|
|
129
|
+
throw new Core.LanternError(`Node ${node.id} not yet completed`);
|
|
129
130
|
}
|
|
130
131
|
return timing;
|
|
131
132
|
}
|
|
@@ -1 +1 @@
|
|
|
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
|
+
{"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 Core from '../core/core.js';\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 Core.LanternError(`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 Core.LanternError(`Node ${node.id} not yet queued`);\n }\n if (!('startTime' in timing)) {\n throw new Core.LanternError(`Node ${node.id} not yet started`);\n }\n if ('bytesDownloaded' in timing) {\n throw new Core.LanternError(`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 Core.LanternError(`Node ${node.id} not yet queued`);\n }\n if (!('startTime' in timing)) {\n throw new Core.LanternError(`Node ${node.id} not yet started`);\n }\n if (!('bytesDownloaded' in timing)) {\n throw new Core.LanternError(`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 Core.LanternError(`Node ${node.id} not yet queued`);\n }\n if (!('startTime' in timing)) {\n throw new Core.LanternError(`Node ${node.id} not yet started`);\n }\n if (!('estimatedTimeElapsed' in timing)) {\n throw new Core.LanternError(`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 Core.LanternError(`Node ${node.id} not yet queued`);\n }\n if (!('startTime' in timing)) {\n throw new Core.LanternError(`Node ${node.id} not yet started`);\n }\n if (!('estimatedTimeElapsed' in timing)) {\n throw new Core.LanternError(`Node ${node.id} not yet in progress`);\n }\n if (!('endTime' in timing)) {\n throw new Core.LanternError(`Node ${node.id} not yet completed`);\n }\n return timing;\n }\n}\n\nexport {SimulatorTimingMap};\n"]}
|
|
@@ -1,6 +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 * as Core from '../core/core.js';
|
|
4
5
|
import * as Graph from '../graph/graph.js';
|
|
5
6
|
import { ConnectionPool } from './ConnectionPool.js';
|
|
6
7
|
import { Constants } from './Constants.js';
|
|
@@ -107,10 +108,10 @@ class Simulator {
|
|
|
107
108
|
// @ts-expect-error
|
|
108
109
|
this._connectionPool = null;
|
|
109
110
|
if (!Number.isFinite(this._rtt)) {
|
|
110
|
-
throw new
|
|
111
|
+
throw new Core.LanternError(`Invalid rtt ${this._rtt}`);
|
|
111
112
|
}
|
|
112
113
|
if (!Number.isFinite(this._throughput)) {
|
|
113
|
-
throw new
|
|
114
|
+
throw new Core.LanternError(`Invalid rtt ${this._throughput}`);
|
|
114
115
|
}
|
|
115
116
|
}
|
|
116
117
|
get rtt() {
|
|
@@ -192,7 +193,7 @@ class Simulator {
|
|
|
192
193
|
return;
|
|
193
194
|
}
|
|
194
195
|
if (node.type !== Graph.BaseNode.types.NETWORK) {
|
|
195
|
-
throw new
|
|
196
|
+
throw new Core.LanternError('Unsupported');
|
|
196
197
|
}
|
|
197
198
|
// If a network request is connectionless, we can always start it, so skip the connection checks
|
|
198
199
|
if (!node.isConnectionless) {
|
|
@@ -231,7 +232,7 @@ class Simulator {
|
|
|
231
232
|
if (node.type === Graph.BaseNode.types.NETWORK) {
|
|
232
233
|
return this._estimateNetworkTimeRemaining(node);
|
|
233
234
|
}
|
|
234
|
-
throw new
|
|
235
|
+
throw new Core.LanternError('Unsupported');
|
|
235
236
|
}
|
|
236
237
|
_estimateCPUTimeRemaining(cpuNode) {
|
|
237
238
|
const timingData = this._nodeTimings.getCpuStarted(cpuNode);
|
|
@@ -299,10 +300,10 @@ class Simulator {
|
|
|
299
300
|
return;
|
|
300
301
|
}
|
|
301
302
|
if (node.type !== Graph.BaseNode.types.NETWORK) {
|
|
302
|
-
throw new
|
|
303
|
+
throw new Core.LanternError('Unsupported');
|
|
303
304
|
}
|
|
304
305
|
if (!('bytesDownloaded' in timingData)) {
|
|
305
|
-
throw new
|
|
306
|
+
throw new Core.LanternError('Invalid timing data');
|
|
306
307
|
}
|
|
307
308
|
const request = node.request;
|
|
308
309
|
const connection = this._connectionPool.acquireActiveConnectionFromRequest(request);
|
|
@@ -364,7 +365,7 @@ class Simulator {
|
|
|
364
365
|
*/
|
|
365
366
|
simulate(graph, options) {
|
|
366
367
|
if (Graph.BaseNode.hasCycle(graph)) {
|
|
367
|
-
throw new
|
|
368
|
+
throw new Core.LanternError('Cannot simulate graph with cycle');
|
|
368
369
|
}
|
|
369
370
|
options = Object.assign({
|
|
370
371
|
label: undefined,
|
|
@@ -391,7 +392,7 @@ class Simulator {
|
|
|
391
392
|
if (!nodesInProgress.size) {
|
|
392
393
|
// Interplay between fromDiskCache and connectionReused can be incorrect,
|
|
393
394
|
// have to give up.
|
|
394
|
-
throw new
|
|
395
|
+
throw new Core.LanternError('Failed to start a node');
|
|
395
396
|
}
|
|
396
397
|
// set the available throughput for all connections based on # inflight
|
|
397
398
|
this._updateNetworkCapacity();
|
|
@@ -400,7 +401,7 @@ class Simulator {
|
|
|
400
401
|
totalElapsedTime += minimumTime;
|
|
401
402
|
// While this is no longer strictly necessary, it's always better than hanging
|
|
402
403
|
if (!Number.isFinite(minimumTime) || iteration > 100000) {
|
|
403
|
-
throw new
|
|
404
|
+
throw new Core.LanternError('Simulation failed, depth exceeded');
|
|
404
405
|
}
|
|
405
406
|
iteration++;
|
|
406
407
|
// update how far each node will progress until that point
|