@paulirish/trace_engine 0.0.26 → 0.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/models/trace/LanternComputationData.d.ts +4 -4
- package/models/trace/LanternComputationData.js +4 -4
- package/models/trace/LanternComputationData.js.map +1 -1
- package/models/trace/lantern/core/LanternError.d.ts +3 -0
- package/models/trace/lantern/core/LanternError.js +7 -0
- package/models/trace/lantern/core/LanternError.js.map +1 -0
- package/models/trace/lantern/core/NetworkAnalyzer.d.ts +112 -0
- package/models/trace/lantern/core/NetworkAnalyzer.js +486 -0
- package/models/trace/lantern/core/NetworkAnalyzer.js.map +1 -0
- package/models/trace/lantern/core/bundle-tsconfig.json +1 -0
- package/models/trace/lantern/core/core-tsconfig.json +43 -0
- package/models/trace/lantern/core/core.d.ts +2 -0
- package/models/trace/lantern/core/core.js +6 -0
- package/models/trace/lantern/core/core.js.map +1 -0
- package/models/trace/lantern/core/devtools_entrypoint-bundle-typescript-tsconfig.json +42 -0
- package/models/trace/lantern/graph/BaseNode.d.ts +91 -0
- package/models/trace/lantern/graph/BaseNode.js +268 -0
- package/models/trace/lantern/graph/BaseNode.js.map +1 -0
- package/models/trace/lantern/graph/CPUNode.d.ts +24 -0
- package/models/trace/lantern/graph/CPUNode.js +64 -0
- package/models/trace/lantern/graph/CPUNode.js.map +1 -0
- package/models/trace/lantern/graph/NetworkNode.d.ts +22 -0
- package/models/trace/lantern/graph/NetworkNode.js +83 -0
- package/models/trace/lantern/graph/NetworkNode.js.map +1 -0
- package/models/trace/lantern/graph/PageDependencyGraph.d.ts +43 -0
- package/models/trace/lantern/graph/PageDependencyGraph.js +509 -0
- package/models/trace/lantern/graph/PageDependencyGraph.js.map +1 -0
- package/models/trace/lantern/graph/bundle-tsconfig.json +1 -0
- package/models/trace/lantern/graph/devtools_entrypoint-bundle-typescript-tsconfig.json +42 -0
- package/models/trace/lantern/graph/graph-tsconfig.json +48 -0
- package/models/trace/lantern/graph/graph.d.ts +4 -0
- package/models/trace/lantern/graph/graph.js +8 -0
- package/models/trace/lantern/graph/graph.js.map +1 -0
- package/models/trace/lantern/lantern-tsconfig.json +13 -24
- package/models/trace/lantern/lantern.d.ts +6 -29
- package/models/trace/lantern/lantern.js +6 -29
- package/models/trace/lantern/lantern.js.map +1 -1
- package/models/trace/lantern/metrics/FirstContentfulPaint.d.ts +10 -12
- package/models/trace/lantern/metrics/FirstContentfulPaint.js +3 -3
- package/models/trace/lantern/metrics/FirstContentfulPaint.js.map +1 -1
- package/models/trace/lantern/metrics/Interactive.d.ts +9 -9
- package/models/trace/lantern/metrics/Interactive.js +4 -5
- package/models/trace/lantern/metrics/Interactive.js.map +1 -1
- package/models/trace/lantern/metrics/LargestContentfulPaint.d.ts +10 -9
- package/models/trace/lantern/metrics/LargestContentfulPaint.js +4 -5
- package/models/trace/lantern/metrics/LargestContentfulPaint.js.map +1 -1
- package/models/trace/lantern/metrics/MaxPotentialFID.d.ts +9 -9
- package/models/trace/lantern/metrics/MaxPotentialFID.js +3 -4
- package/models/trace/lantern/metrics/MaxPotentialFID.js.map +1 -1
- package/models/trace/lantern/metrics/Metric.d.ts +31 -13
- package/models/trace/lantern/metrics/Metric.js +2 -3
- package/models/trace/lantern/metrics/Metric.js.map +1 -1
- package/models/trace/lantern/metrics/SpeedIndex.d.ts +10 -10
- package/models/trace/lantern/metrics/SpeedIndex.js +3 -4
- package/models/trace/lantern/metrics/SpeedIndex.js.map +1 -1
- package/models/trace/lantern/metrics/TotalBlockingTime.d.ts +9 -9
- package/models/trace/lantern/metrics/TotalBlockingTime.js +3 -4
- package/models/trace/lantern/metrics/TotalBlockingTime.js.map +1 -1
- package/models/trace/lantern/metrics/bundle-tsconfig.json +1 -0
- package/models/trace/lantern/metrics/devtools_entrypoint-bundle-typescript-tsconfig.json +42 -0
- package/models/trace/lantern/metrics/metrics-tsconfig.json +58 -0
- package/models/trace/lantern/metrics/metrics.d.ts +7 -14
- package/models/trace/lantern/metrics/metrics.js +7 -7
- package/models/trace/lantern/metrics/metrics.js.map +1 -1
- package/models/trace/lantern/simulation/ConnectionPool.d.ts +1 -1
- package/models/trace/lantern/simulation/ConnectionPool.js +3 -3
- package/models/trace/lantern/simulation/ConnectionPool.js.map +1 -1
- package/models/trace/lantern/simulation/DNSCache.d.ts +1 -1
- package/models/trace/lantern/simulation/DNSCache.js.map +1 -1
- package/models/trace/lantern/simulation/SimulationTimingMap.d.ts +15 -17
- package/models/trace/lantern/simulation/SimulationTimingMap.js +2 -2
- package/models/trace/lantern/simulation/SimulationTimingMap.js.map +1 -1
- package/models/trace/lantern/simulation/Simulator.d.ts +24 -22
- package/models/trace/lantern/simulation/Simulator.js +10 -10
- package/models/trace/lantern/simulation/Simulator.js.map +1 -1
- package/models/trace/lantern/simulation/bundle-tsconfig.json +1 -0
- package/models/trace/lantern/simulation/devtools_entrypoint-bundle-typescript-tsconfig.json +42 -0
- package/models/trace/lantern/simulation/simulation-tsconfig.json +50 -0
- package/models/trace/lantern/simulation/simulation.d.ts +6 -21
- package/models/trace/lantern/simulation/simulation.js +6 -7
- package/models/trace/lantern/simulation/simulation.js.map +1 -1
- package/models/trace/lantern/types/{lantern.d.ts → Lantern.d.ts} +21 -27
- package/models/trace/lantern/types/Lantern.js +24 -0
- package/models/trace/lantern/types/Lantern.js.map +1 -0
- package/models/trace/lantern/types/bundle-tsconfig.json +1 -0
- package/models/trace/lantern/types/devtools_entrypoint-bundle-typescript-tsconfig.json +42 -0
- package/models/trace/lantern/types/types-tsconfig.json +42 -0
- package/models/trace/lantern/types/types.d.ts +1 -0
- package/models/trace/lantern/types/{lantern.js → types.js} +2 -2
- package/models/trace/lantern/types/types.js.map +1 -0
- package/package.json +1 -1
- package/models/trace/lantern/types/lantern.js.map +0 -1
|
@@ -1,10 +1,9 @@
|
|
|
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
|
|
5
|
-
import { Metric } from './Metric.js';
|
|
4
|
+
import * as Graph from '../graph/graph.js';
|
|
5
|
+
import { Metric, } from './Metric.js';
|
|
6
6
|
class MaxPotentialFID extends Metric {
|
|
7
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
8
7
|
static get coefficients() {
|
|
9
8
|
return {
|
|
10
9
|
intercept: 0,
|
|
@@ -41,7 +40,7 @@ class MaxPotentialFID extends Metric {
|
|
|
41
40
|
}
|
|
42
41
|
static getTimingsAfterFCP(nodeTimings, fcpTimeInMs) {
|
|
43
42
|
return Array.from(nodeTimings.entries())
|
|
44
|
-
.filter(([node, timing]) => node.type === BaseNode.types.CPU && timing.endTime > fcpTimeInMs)
|
|
43
|
+
.filter(([node, timing]) => node.type === Graph.BaseNode.types.CPU && timing.endTime > fcpTimeInMs)
|
|
45
44
|
.map(([_, timing]) => timing);
|
|
46
45
|
}
|
|
47
46
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MaxPotentialFID.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/metrics/MaxPotentialFID.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,
|
|
1
|
+
{"version":3,"file":"MaxPotentialFID.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/metrics/MaxPotentialFID.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,eAAgB,SAAQ,MAAM;IAClC,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,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACvC,CAAC;QAED,4FAA4F;QAC5F,wFAAwF;QACxF,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;YAC/C,MAAM,CAAC,SAAS,CAAC,kBAAkB,CAAC,QAAQ,CAAC;QAErF,MAAM,OAAO,GAAG,eAAe,CAAC,kBAAkB,CAC9C,UAAU,CAAC,WAAW,EACtB,WAAW,CACd,CAAC;QAEF,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjE,WAAW,EAAE,UAAU,CAAC,WAAW;SACpC,CAAC;IACJ,CAAC;IAED,MAAM,CAAU,OAAO,CAAC,IAAgC,EAAE,MAAmC;QAE3F,MAAM,SAAS,GAAG,MAAM,EAAE,SAAS,CAAC;QACpC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;QAC/E,CAAC;QAED,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,CAAC,kBAAkB,CAAC,WAA6C,EAAE,WAAmB;QAE1F,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;aACnC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,IAAI,MAAM,CAAC,OAAO,GAAG,WAAW,CAAC;aAClG,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;CACF;AAED,OAAO,EAAC,eAAe,EAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Graph from '../graph/graph.js';\nimport type * as 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\nclass MaxPotentialFID 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 Error('missing fcpResult');\n }\n\n // Intentionally use the opposite FCP estimate, a more pessimistic FCP means that more tasks\n // are excluded from the FID computation, so a higher FCP means lower FID for same work.\n const fcpTimeInMs = extras.optimistic ? extras.fcpResult.pessimisticEstimate.timeInMs :\n extras.fcpResult.optimisticEstimate.timeInMs;\n\n const timings = MaxPotentialFID.getTimingsAfterFCP(\n simulation.nodeTimings,\n fcpTimeInMs,\n );\n\n return {\n timeInMs: Math.max(...timings.map(timing => timing.duration), 16),\n nodeTimings: simulation.nodeTimings,\n };\n }\n\n static override compute(data: MetricComputationDataInput, extras?: Omit<Extras, 'optimistic'>):\n Promise<MetricResult> {\n const fcpResult = extras?.fcpResult;\n if (!fcpResult) {\n throw new Error('FCP is required to calculate the Max Potential FID metric');\n }\n\n return super.compute(data, extras);\n }\n\n static getTimingsAfterFCP(nodeTimings: Simulation.Result['nodeTimings'], fcpTimeInMs: number):\n Array<{duration: number}> {\n return Array.from(nodeTimings.entries())\n .filter(([node, timing]) => node.type === Graph.BaseNode.types.CPU && timing.endTime > fcpTimeInMs)\n .map(([_, timing]) => timing);\n }\n}\n\nexport {MaxPotentialFID};\n"]}
|
|
@@ -1,26 +1,44 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import type * as
|
|
1
|
+
import * as Graph from '../graph/graph.js';
|
|
2
|
+
import type * as Simulation from '../simulation/simulation.js';
|
|
3
|
+
import type * as Types from '../types/types.js';
|
|
4
|
+
export interface MetricComputationDataInput {
|
|
5
|
+
simulator: Simulation.Simulator;
|
|
6
|
+
graph: Graph.Node<unknown>;
|
|
7
|
+
processedNavigation: Types.Simulation.ProcessedNavigation;
|
|
8
|
+
}
|
|
9
|
+
export interface MetricCoefficients {
|
|
10
|
+
intercept: number;
|
|
11
|
+
optimistic: number;
|
|
12
|
+
pessimistic: number;
|
|
13
|
+
}
|
|
14
|
+
export interface MetricResult<T = Types.AnyNetworkObject> {
|
|
15
|
+
timing: number;
|
|
16
|
+
timestamp?: never;
|
|
17
|
+
optimisticEstimate: Simulation.Result<T>;
|
|
18
|
+
pessimisticEstimate: Simulation.Result<T>;
|
|
19
|
+
optimisticGraph: Graph.Node<T>;
|
|
20
|
+
pessimisticGraph: Graph.Node;
|
|
21
|
+
}
|
|
4
22
|
export interface Extras {
|
|
5
23
|
optimistic: boolean;
|
|
6
|
-
fcpResult?:
|
|
7
|
-
lcpResult?:
|
|
8
|
-
interactiveResult?:
|
|
24
|
+
fcpResult?: MetricResult;
|
|
25
|
+
lcpResult?: MetricResult;
|
|
26
|
+
interactiveResult?: MetricResult;
|
|
9
27
|
observedSpeedIndex?: number;
|
|
10
28
|
}
|
|
11
29
|
declare class Metric {
|
|
12
|
-
static getScriptUrls(dependencyGraph: Node, treatNodeAsRenderBlocking?: (node: NetworkNode) => boolean): Set<string>;
|
|
13
|
-
static get coefficients():
|
|
30
|
+
static getScriptUrls(dependencyGraph: Graph.Node, treatNodeAsRenderBlocking?: (node: Graph.NetworkNode) => boolean): Set<string>;
|
|
31
|
+
static get coefficients(): MetricCoefficients;
|
|
14
32
|
/**
|
|
15
33
|
* Returns the coefficients, scaled by the throttling settings if needed by the metric.
|
|
16
34
|
* Some lantern metrics (speed-index) use components in their estimate that are not
|
|
17
35
|
* from the simulator. In this case, we need to adjust the coefficients as the target throttling
|
|
18
36
|
* settings change.
|
|
19
37
|
*/
|
|
20
|
-
static getScaledCoefficients(rttMs: number):
|
|
21
|
-
static getOptimisticGraph(dependencyGraph: Node, processedNavigation:
|
|
22
|
-
static getPessimisticGraph(dependencyGraph: Node, processedNavigation:
|
|
23
|
-
static getEstimateFromSimulation(simulationResult:
|
|
24
|
-
static compute(data:
|
|
38
|
+
static getScaledCoefficients(rttMs: number): MetricCoefficients;
|
|
39
|
+
static getOptimisticGraph(dependencyGraph: Graph.Node, processedNavigation: Types.Simulation.ProcessedNavigation): Graph.Node;
|
|
40
|
+
static getPessimisticGraph(dependencyGraph: Graph.Node, processedNavigation: Types.Simulation.ProcessedNavigation): Graph.Node;
|
|
41
|
+
static getEstimateFromSimulation(simulationResult: Simulation.Result, extras: Extras): Simulation.Result;
|
|
42
|
+
static compute(data: MetricComputationDataInput, extras?: Omit<Extras, 'optimistic'>): Promise<MetricResult>;
|
|
25
43
|
}
|
|
26
44
|
export { Metric };
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// Copyright 2024 The Chromium Authors. All rights reserved.
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
|
-
import
|
|
4
|
+
import * as Graph from '../graph/graph.js';
|
|
5
5
|
class Metric {
|
|
6
6
|
static getScriptUrls(dependencyGraph, treatNodeAsRenderBlocking) {
|
|
7
7
|
const scriptUrls = new Set();
|
|
8
8
|
dependencyGraph.traverse(node => {
|
|
9
|
-
if (node.type !== BaseNode.types.NETWORK) {
|
|
9
|
+
if (node.type !== Graph.BaseNode.types.NETWORK) {
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
12
|
if (node.request.resourceType !== 'Script') {
|
|
@@ -18,7 +18,6 @@ class Metric {
|
|
|
18
18
|
});
|
|
19
19
|
return scriptUrls;
|
|
20
20
|
}
|
|
21
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
22
21
|
static get coefficients() {
|
|
23
22
|
throw new Error('coefficients unimplemented!');
|
|
24
23
|
}
|
|
@@ -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,
|
|
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 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 Error('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 Error('Optimistic graph unimplemented!');\n }\n\n static getPessimisticGraph(dependencyGraph: Graph.Node, processedNavigation: Types.Simulation.ProcessedNavigation):\n Graph.Node {\n throw new Error('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 async compute(data: MetricComputationDataInput, extras?: Omit<Extras, 'optimistic'>): Promise<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"]}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type * as
|
|
3
|
-
import { type Extras, Metric } from './Metric.js';
|
|
1
|
+
import * as Graph from '../graph/graph.js';
|
|
2
|
+
import type * as Simulation from '../simulation/simulation.js';
|
|
3
|
+
import { type Extras, Metric, type MetricCoefficients, type MetricComputationDataInput, type MetricResult } from './Metric.js';
|
|
4
4
|
declare class SpeedIndex extends Metric {
|
|
5
|
-
static get coefficients():
|
|
6
|
-
static getScaledCoefficients(rttMs: number):
|
|
7
|
-
static getOptimisticGraph(dependencyGraph: Node): Node;
|
|
8
|
-
static getPessimisticGraph(dependencyGraph: Node): Node;
|
|
9
|
-
static getEstimateFromSimulation(simulationResult:
|
|
10
|
-
static compute(data:
|
|
5
|
+
static get coefficients(): MetricCoefficients;
|
|
6
|
+
static getScaledCoefficients(rttMs: number): MetricCoefficients;
|
|
7
|
+
static getOptimisticGraph(dependencyGraph: Graph.Node): Graph.Node;
|
|
8
|
+
static getPessimisticGraph(dependencyGraph: Graph.Node): Graph.Node;
|
|
9
|
+
static getEstimateFromSimulation(simulationResult: Simulation.Result, extras: Extras): Simulation.Result;
|
|
10
|
+
static compute(data: MetricComputationDataInput, extras?: Omit<Extras, 'optimistic'>): Promise<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
|
|
@@ -20,6 +20,6 @@ declare class SpeedIndex extends Metric {
|
|
|
20
20
|
*
|
|
21
21
|
* @see https://docs.google.com/document/d/1qJWXwxoyVLVadezIp_Tgdk867G3tDNkkVRvUJSH3K1E/edit#
|
|
22
22
|
*/
|
|
23
|
-
static computeLayoutBasedSpeedIndex(nodeTimings:
|
|
23
|
+
static computeLayoutBasedSpeedIndex(nodeTimings: Simulation.Result['nodeTimings'], fcpTimeInMs: number): number;
|
|
24
24
|
}
|
|
25
25
|
export { SpeedIndex };
|
|
@@ -1,11 +1,10 @@
|
|
|
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
|
|
5
|
-
import { Metric } from './Metric.js';
|
|
4
|
+
import * as Graph from '../graph/graph.js';
|
|
5
|
+
import { Metric, } from './Metric.js';
|
|
6
6
|
const mobileSlow4GRtt = 150;
|
|
7
7
|
class SpeedIndex extends Metric {
|
|
8
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
9
8
|
static get coefficients() {
|
|
10
9
|
return {
|
|
11
10
|
// Note that the optimistic estimate is based on the real observed speed index rather than a
|
|
@@ -82,7 +81,7 @@ class SpeedIndex extends Metric {
|
|
|
82
81
|
static computeLayoutBasedSpeedIndex(nodeTimings, fcpTimeInMs) {
|
|
83
82
|
const layoutWeights = [];
|
|
84
83
|
for (const [node, timing] of nodeTimings.entries()) {
|
|
85
|
-
if (node.type !== BaseNode.types.CPU) {
|
|
84
|
+
if (node.type !== Graph.BaseNode.types.CPU) {
|
|
86
85
|
continue;
|
|
87
86
|
}
|
|
88
87
|
if (node.childEvents.some(x => x.name === 'Layout')) {
|
|
@@ -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,
|
|
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 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 Error('missing fcpResult');\n }\n if (extras.observedSpeedIndex === undefined) {\n throw new Error('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 async compute(data: MetricComputationDataInput, extras?: Omit<Extras, 'optimistic'>):\n Promise<MetricResult> {\n const fcpResult = extras?.fcpResult;\n if (!fcpResult) {\n throw new Error('FCP is required to calculate the SpeedIndex metric');\n }\n\n const metricResult = await 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"]}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type * as
|
|
3
|
-
import { type Extras, Metric } from './Metric.js';
|
|
1
|
+
import * as Graph from '../graph/graph.js';
|
|
2
|
+
import type * as Simulation from '../simulation/simulation.js';
|
|
3
|
+
import { type Extras, Metric, type MetricCoefficients, type MetricComputationDataInput, type MetricResult } from './Metric.js';
|
|
4
4
|
declare class TotalBlockingTime extends Metric {
|
|
5
|
-
static get coefficients():
|
|
6
|
-
static getOptimisticGraph(dependencyGraph: Node): Node;
|
|
7
|
-
static getPessimisticGraph(dependencyGraph: Node): Node;
|
|
8
|
-
static getEstimateFromSimulation(simulation:
|
|
9
|
-
static compute(data:
|
|
10
|
-
static getTopLevelEvents(nodeTimings:
|
|
5
|
+
static get coefficients(): MetricCoefficients;
|
|
6
|
+
static getOptimisticGraph(dependencyGraph: Graph.Node): Graph.Node;
|
|
7
|
+
static getPessimisticGraph(dependencyGraph: Graph.Node): Graph.Node;
|
|
8
|
+
static getEstimateFromSimulation(simulation: Simulation.Result, extras: Extras): Simulation.Result;
|
|
9
|
+
static compute(data: MetricComputationDataInput, extras?: Omit<Extras, 'optimistic'>): Promise<MetricResult>;
|
|
10
|
+
static getTopLevelEvents(nodeTimings: Simulation.Result['nodeTimings'], minDurationMs: number): {
|
|
11
11
|
start: number;
|
|
12
12
|
end: number;
|
|
13
13
|
duration: number;
|
|
@@ -1,11 +1,10 @@
|
|
|
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
|
|
5
|
-
import { Metric } from './Metric.js';
|
|
4
|
+
import * as Graph from '../graph/graph.js';
|
|
5
|
+
import { Metric, } from './Metric.js';
|
|
6
6
|
import { BLOCKING_TIME_THRESHOLD, calculateSumOfBlockingTime } from './TBTUtils.js';
|
|
7
7
|
class TotalBlockingTime extends Metric {
|
|
8
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
9
8
|
static get coefficients() {
|
|
10
9
|
return {
|
|
11
10
|
intercept: 0,
|
|
@@ -59,7 +58,7 @@ class TotalBlockingTime extends Metric {
|
|
|
59
58
|
static getTopLevelEvents(nodeTimings, minDurationMs) {
|
|
60
59
|
const events = [];
|
|
61
60
|
for (const [node, timing] of nodeTimings.entries()) {
|
|
62
|
-
if (node.type !== BaseNode.types.CPU) {
|
|
61
|
+
if (node.type !== Graph.BaseNode.types.CPU) {
|
|
63
62
|
continue;
|
|
64
63
|
}
|
|
65
64
|
// Filtering out events below minimum duration.
|
|
@@ -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,
|
|
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 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 Error('missing fcpResult');\n }\n if (!extras.interactiveResult) {\n throw new Error('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 async compute(data: MetricComputationDataInput, extras?: Omit<Extras, 'optimistic'>):\n Promise<MetricResult> {\n const fcpResult = extras?.fcpResult;\n if (!fcpResult) {\n throw new Error('FCP is required to calculate the TBT metric');\n }\n\n const interactiveResult = extras?.fcpResult;\n if (!interactiveResult) {\n throw new Error('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"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"compilerOptions":{"composite":true,"outDir":".","baseUrl":".","rootDir":"../../../../../../../../front_end/models/trace/lantern/metrics"},"files":["../../../../../../../../front_end/models/trace/lantern/metrics/metrics.ts"],"references":[{"path":"./metrics-tsconfig.json"}]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"allowJs": true,
|
|
4
|
+
"checkJs": true,
|
|
5
|
+
"composite": true,
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"experimentalDecorators": true,
|
|
8
|
+
"forceConsistentCasingInFileNames": true,
|
|
9
|
+
"inlineSources": true,
|
|
10
|
+
"lib": [
|
|
11
|
+
"esnext",
|
|
12
|
+
"dom",
|
|
13
|
+
"dom.iterable"
|
|
14
|
+
],
|
|
15
|
+
"module": "esnext",
|
|
16
|
+
"noEmitOnError": true,
|
|
17
|
+
"noFallthroughCasesInSwitch": true,
|
|
18
|
+
"noImplicitOverride": true,
|
|
19
|
+
"noImplicitReturns": true,
|
|
20
|
+
"noUnusedLocals": false,
|
|
21
|
+
"outDir": ".",
|
|
22
|
+
"rootDir": "../../../../../../../../front_end/models/trace/lantern/metrics",
|
|
23
|
+
"skipLibCheck": true,
|
|
24
|
+
"sourceMap": true,
|
|
25
|
+
"strict": true,
|
|
26
|
+
"target": "esnext",
|
|
27
|
+
"tsBuildInfoFile": "devtools_entrypoint-bundle-typescript-tsconfig.json.tsbuildinfo",
|
|
28
|
+
"typeRoots": [],
|
|
29
|
+
"useUnknownInCatchVariables": false
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"../../../../../../../../front_end/models/trace/lantern/metrics/metrics.ts",
|
|
33
|
+
"../../../../../../../../front_end/legacy/legacy-defs.d.ts",
|
|
34
|
+
"../../../../../../../../front_end/global_typings/global_defs.d.ts",
|
|
35
|
+
"../../../../../../../../node_modules/@types/filesystem/index.d.ts"
|
|
36
|
+
],
|
|
37
|
+
"references": [
|
|
38
|
+
{
|
|
39
|
+
"path": "./metrics-tsconfig.json"
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"allowJs": true,
|
|
4
|
+
"checkJs": true,
|
|
5
|
+
"composite": true,
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"experimentalDecorators": true,
|
|
8
|
+
"forceConsistentCasingInFileNames": true,
|
|
9
|
+
"inlineSources": true,
|
|
10
|
+
"lib": [
|
|
11
|
+
"esnext",
|
|
12
|
+
"dom",
|
|
13
|
+
"dom.iterable"
|
|
14
|
+
],
|
|
15
|
+
"module": "esnext",
|
|
16
|
+
"noEmitOnError": true,
|
|
17
|
+
"noFallthroughCasesInSwitch": true,
|
|
18
|
+
"noImplicitOverride": true,
|
|
19
|
+
"noImplicitReturns": true,
|
|
20
|
+
"noUnusedLocals": false,
|
|
21
|
+
"outDir": ".",
|
|
22
|
+
"rootDir": "../../../../../../../../front_end/models/trace/lantern/metrics",
|
|
23
|
+
"skipLibCheck": true,
|
|
24
|
+
"sourceMap": true,
|
|
25
|
+
"strict": true,
|
|
26
|
+
"target": "esnext",
|
|
27
|
+
"tsBuildInfoFile": "metrics-tsconfig.json.tsbuildinfo",
|
|
28
|
+
"typeRoots": [],
|
|
29
|
+
"useUnknownInCatchVariables": false
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"../../../../../../../../front_end/models/trace/lantern/metrics/FirstContentfulPaint.ts",
|
|
33
|
+
"../../../../../../../../front_end/models/trace/lantern/metrics/Interactive.ts",
|
|
34
|
+
"../../../../../../../../front_end/models/trace/lantern/metrics/LargestContentfulPaint.ts",
|
|
35
|
+
"../../../../../../../../front_end/models/trace/lantern/metrics/MaxPotentialFID.ts",
|
|
36
|
+
"../../../../../../../../front_end/models/trace/lantern/metrics/Metric.ts",
|
|
37
|
+
"../../../../../../../../front_end/models/trace/lantern/metrics/SpeedIndex.ts",
|
|
38
|
+
"../../../../../../../../front_end/models/trace/lantern/metrics/TBTUtils.ts",
|
|
39
|
+
"../../../../../../../../front_end/models/trace/lantern/metrics/TotalBlockingTime.ts",
|
|
40
|
+
"../../../../../../../../front_end/legacy/legacy-defs.d.ts",
|
|
41
|
+
"../../../../../../../../front_end/global_typings/global_defs.d.ts",
|
|
42
|
+
"../../../../../../../../node_modules/@types/filesystem/index.d.ts"
|
|
43
|
+
],
|
|
44
|
+
"references": [
|
|
45
|
+
{
|
|
46
|
+
"path": "../core/bundle-tsconfig.json"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"path": "../graph/bundle-tsconfig.json"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"path": "../simulation/bundle-tsconfig.json"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"path": "../types/bundle-tsconfig.json"
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
@@ -1,15 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export
|
|
8
|
-
export { Interactive } from './Interactive.js';
|
|
9
|
-
export { LargestContentfulPaint } from './LargestContentfulPaint.js';
|
|
10
|
-
export { MaxPotentialFID } from './MaxPotentialFID.js';
|
|
11
|
-
export { Metric, Extras } from './Metric.js';
|
|
12
|
-
export { SpeedIndex } from './SpeedIndex.js';
|
|
1
|
+
export * from './FirstContentfulPaint.js';
|
|
2
|
+
export * from './Interactive.js';
|
|
3
|
+
export * from './LargestContentfulPaint.js';
|
|
4
|
+
export * from './MaxPotentialFID.js';
|
|
5
|
+
export * from './Metric.js';
|
|
6
|
+
export * from './SpeedIndex.js';
|
|
7
|
+
export * from './TotalBlockingTime.js';
|
|
13
8
|
export * as TBTUtils from './TBTUtils.js';
|
|
14
|
-
export { TotalBlockingTime } from './TotalBlockingTime.js';
|
|
15
|
-
export type Result<T = Lantern.AnyNetworkObject> = Lantern.Metrics.Result<T>;
|
|
@@ -1,12 +1,12 @@
|
|
|
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
|
-
export
|
|
5
|
-
export
|
|
6
|
-
export
|
|
7
|
-
export
|
|
8
|
-
export
|
|
9
|
-
export
|
|
4
|
+
export * from './FirstContentfulPaint.js';
|
|
5
|
+
export * from './Interactive.js';
|
|
6
|
+
export * from './LargestContentfulPaint.js';
|
|
7
|
+
export * from './MaxPotentialFID.js';
|
|
8
|
+
export * from './Metric.js';
|
|
9
|
+
export * from './SpeedIndex.js';
|
|
10
|
+
export * from './TotalBlockingTime.js';
|
|
10
11
|
export * as TBTUtils from './TBTUtils.js';
|
|
11
|
-
export { TotalBlockingTime } from './TotalBlockingTime.js';
|
|
12
12
|
//# sourceMappingURL=metrics.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/metrics/metrics.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;
|
|
1
|
+
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/metrics/metrics.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,wBAAwB,CAAC;AACvC,OAAO,KAAK,QAAQ,MAAM,eAAe,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\nexport * from './FirstContentfulPaint.js';\nexport * from './Interactive.js';\nexport * from './LargestContentfulPaint.js';\nexport * from './MaxPotentialFID.js';\nexport * from './Metric.js';\nexport * from './SpeedIndex.js';\nexport * from './TotalBlockingTime.js';\nexport * as TBTUtils from './TBTUtils.js';\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright 2024 The Chromium Authors. All rights reserved.
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
|
-
import
|
|
4
|
+
import * as Core from '../core/core.js';
|
|
5
5
|
import { TCPConnection } from './TCPConnection.js';
|
|
6
6
|
const DEFAULT_SERVER_RESPONSE_TIME = 30;
|
|
7
7
|
const TLS_SCHEMES = ['https', 'wss'];
|
|
@@ -21,7 +21,7 @@ export class ConnectionPool {
|
|
|
21
21
|
this._connectionsByOrigin = new Map();
|
|
22
22
|
this._connectionsByRequest = new Map();
|
|
23
23
|
this._connectionsInUse = new Set();
|
|
24
|
-
this._connectionReusedByRequestId = NetworkAnalyzer.estimateIfConnectionWasReused(records, {
|
|
24
|
+
this._connectionReusedByRequestId = Core.NetworkAnalyzer.estimateIfConnectionWasReused(records, {
|
|
25
25
|
forceCoarseEstimates: true,
|
|
26
26
|
});
|
|
27
27
|
this._initializeConnections();
|
|
@@ -33,7 +33,7 @@ export class ConnectionPool {
|
|
|
33
33
|
const connectionReused = this._connectionReusedByRequestId;
|
|
34
34
|
const additionalRttByOrigin = this._options.additionalRttByOrigin;
|
|
35
35
|
const serverResponseTimeByOrigin = this._options.serverResponseTimeByOrigin;
|
|
36
|
-
const recordsByOrigin = NetworkAnalyzer.groupByOrigin(this._records);
|
|
36
|
+
const recordsByOrigin = Core.NetworkAnalyzer.groupByOrigin(this._records);
|
|
37
37
|
for (const [origin, requests] of recordsByOrigin.entries()) {
|
|
38
38
|
const connections = [];
|
|
39
39
|
const additionalRtt = additionalRttByOrigin.get(origin) || 0;
|
|
@@ -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;
|
|
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"]}
|