Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core: remove first-meaningful-paint metric #16047

Merged
merged 12 commits into from
Jun 7, 2024
3 changes: 0 additions & 3 deletions cli/test/smokehouse/test-definitions/perf-preload.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,6 @@ const expectations = {
'speed-index': {
score: '>=0.80', // primarily just making sure it didn't fail/go crazy, specific value isn't that important
},
'first-meaningful-paint': {
score: '>=0.90', // primarily just making sure it didn't fail/go crazy, specific value isn't that important
},
'interactive': {
score: '>=0.90', // primarily just making sure it didn't fail/go crazy, specific value isn't that important
},
Expand Down
52 changes: 5 additions & 47 deletions core/audits/metrics/first-meaningful-paint.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
* SPDX-License-Identifier: Apache-2.0
*/

// TODO(COMPAT): This is just a shell. Remove in future breaking release.

import {Audit} from '../audit.js';
import * as i18n from '../../lib/i18n/i18n.js';
import {FirstMeaningfulPaint as ComputedFmp} from '../../computed/metrics/first-meaningful-paint.js';

const UIStrings = {
/** Description of the First Meaningful Paint (FMP) metric, which marks the time at which a majority of the content has been painted by the browser. This is displayed within a tooltip when the user hovers on the metric name to see more. No character length limits. The last sentence starting with 'Learn' becomes link text to additional documentation. */
Expand All @@ -32,55 +33,12 @@ class FirstMeaningfulPaint extends Audit {
}

/**
* @return {{mobile: {scoring: LH.Audit.ScoreOptions}, desktop: {scoring: LH.Audit.ScoreOptions}}}
*/
static get defaultOptions() {
return {
mobile: {
// 25th and 5th percentiles HTTPArchive -> median and PODR, then p10 derived from them.
// https://bigquery.cloud.google.com/table/httparchive:lighthouse.2018_04_01_mobile?pli=1
// see https://www.desmos.com/calculator/i4znkdccut
scoring: {
p10: 2336,
median: 4000,
},
},
desktop: {
// SELECT QUANTILES(renderStart, 21) FROM [httparchive:summary_pages.2018_12_15_desktop] LIMIT 1000
scoring: {
p10: 934,
median: 1600,
},
},
};
}

/**
* Audits the page to give a score for First Meaningful Paint.
* @see https://github.com/GoogleChrome/lighthouse/issues/26
* @see https://docs.google.com/document/d/1BR94tJdZLsin5poeet0XoTW60M0SjvOJQttKT-JK8HI/view
* @param {LH.Artifacts} artifacts The artifacts from the gather phase.
* @param {LH.Audit.Context} context
* @return {Promise<LH.Audit.Product>}
*/
static async audit(artifacts, context) {
const trace = artifacts.traces[Audit.DEFAULT_PASS];
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
const gatherContext = artifacts.GatherContext;
const metricComputationData = {trace, devtoolsLog, gatherContext,
settings: context.settings, URL: artifacts.URL};
const metricResult = await ComputedFmp.request(metricComputationData, context);
const options = context.options[context.settings.formFactor];


static async audit() {
return {
score: Audit.computeLogNormalScore(
connorjclark marked this conversation as resolved.
Show resolved Hide resolved
options.scoring,
metricResult.timing
),
numericValue: metricResult.timing,
numericUnit: 'millisecond',
displayValue: str_(i18n.UIStrings.seconds, {timeInMs: metricResult.timing}),
score: null,
notApplicable: true,
};
}
}
Expand Down
6 changes: 0 additions & 6 deletions core/audits/predictive-perf.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import {Audit} from './audit.js';
import * as i18n from '../lib/i18n/i18n.js';
import {LanternFirstContentfulPaint} from '../computed/metrics/lantern-first-contentful-paint.js';
import {LanternFirstMeaningfulPaint} from '../computed/metrics/lantern-first-meaningful-paint.js';
import {LanternInteractive} from '../computed/metrics/lantern-interactive.js';
import {LanternSpeedIndex} from '../computed/metrics/lantern-speed-index.js';
import {LanternLargestContentfulPaint} from '../computed/metrics/lantern-largest-contentful-paint.js';
Expand Down Expand Up @@ -52,7 +51,6 @@ class PredictivePerf extends Audit {
const settings = JSON.parse(JSON.stringify(defaultSettings)); // Use default settings.
const computationData = {trace, devtoolsLog, gatherContext, settings, URL};
const fcp = await LanternFirstContentfulPaint.request(computationData, context);
const fmp = await LanternFirstMeaningfulPaint.request(computationData, context);
const tti = await LanternInteractive.request(computationData, context);
const si = await LanternSpeedIndex.request(computationData, context);
const lcp = await LanternLargestContentfulPaint.request(computationData, context);
Expand All @@ -64,10 +62,6 @@ class PredictivePerf extends Audit {
optimisticFCP: fcp.optimisticEstimate.timeInMs,
pessimisticFCP: fcp.pessimisticEstimate.timeInMs,

roughEstimateOfFMP: fmp.timing,
optimisticFMP: fmp.optimisticEstimate.timeInMs,
pessimisticFMP: fmp.pessimisticEstimate.timeInMs,

roughEstimateOfTTI: tti.timing,
optimisticTTI: tti.optimisticEstimate.timeInMs,
pessimisticTTI: tti.pessimisticEstimate.timeInMs,
Expand Down
44 changes: 0 additions & 44 deletions core/computed/metrics/first-meaningful-paint.js

This file was deleted.

43 changes: 0 additions & 43 deletions core/computed/metrics/lantern-first-meaningful-paint.js

This file was deleted.

6 changes: 0 additions & 6 deletions core/computed/metrics/timing-summary.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {ProcessedNavigation} from '../processed-navigation.js';
import {Speedline} from '../speedline.js';
import {FirstContentfulPaint} from './first-contentful-paint.js';
import {FirstContentfulPaintAllFrames} from './first-contentful-paint-all-frames.js';
import {FirstMeaningfulPaint} from './first-meaningful-paint.js';
import {LargestContentfulPaint} from './largest-contentful-paint.js';
import {LargestContentfulPaintAllFrames} from './largest-contentful-paint-all-frames.js';
import {Interactive} from './interactive.js';
Expand Down Expand Up @@ -51,7 +50,6 @@ class TimingSummary {
const speedline = await Speedline.request(trace, context);
const firstContentfulPaint = await requestOrUndefined(FirstContentfulPaint, metricComputationData);
const firstContentfulPaintAllFrames = await requestOrUndefined(FirstContentfulPaintAllFrames, metricComputationData);
const firstMeaningfulPaint = await requestOrUndefined(FirstMeaningfulPaint, metricComputationData);
const largestContentfulPaint = await requestOrUndefined(LargestContentfulPaint, metricComputationData);
const largestContentfulPaintAllFrames = await requestOrUndefined(LargestContentfulPaintAllFrames, metricComputationData);
const interactive = await requestOrUndefined(Interactive, metricComputationData);
Expand All @@ -74,8 +72,6 @@ class TimingSummary {
firstContentfulPaintTs: firstContentfulPaint?.timestamp,
firstContentfulPaintAllFrames: firstContentfulPaintAllFrames?.timing,
firstContentfulPaintAllFramesTs: firstContentfulPaintAllFrames?.timestamp,
firstMeaningfulPaint: firstMeaningfulPaint?.timing,
firstMeaningfulPaintTs: firstMeaningfulPaint?.timestamp,
largestContentfulPaint: largestContentfulPaint?.timing,
largestContentfulPaintTs: largestContentfulPaint?.timestamp,
largestContentfulPaintAllFrames: largestContentfulPaintAllFrames?.timing,
Expand Down Expand Up @@ -107,8 +103,6 @@ class TimingSummary {
observedFirstContentfulPaintTs: processedNavigation?.timestamps.firstContentfulPaint,
observedFirstContentfulPaintAllFrames: processedNavigation?.timings.firstContentfulPaintAllFrames,
observedFirstContentfulPaintAllFramesTs: processedNavigation?.timestamps.firstContentfulPaintAllFrames,
observedFirstMeaningfulPaint: processedNavigation?.timings.firstMeaningfulPaint,
observedFirstMeaningfulPaintTs: processedNavigation?.timestamps.firstMeaningfulPaint,
observedLargestContentfulPaint: processedNavigation?.timings.largestContentfulPaint,
observedLargestContentfulPaintTs: processedNavigation?.timestamps.largestContentfulPaint,
observedLargestContentfulPaintAllFrames: processedNavigation?.timings.largestContentfulPaintAllFrames,
Expand Down
64 changes: 0 additions & 64 deletions core/lib/lantern/metrics/first-meaningful-paint.js

This file was deleted.

32 changes: 1 addition & 31 deletions core/lib/tracehouse/trace-processor.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* various tools. This artifact will take a trace and then:
*
* 1. Find the TracingStartedInPage and navigationStart events of our intended tab & frame.
* 2. Find the firstContentfulPaint and marked firstMeaningfulPaint events
* 2. Find the firstContentfulPaint and marked largestContentfulPaint events
* 3. Isolate only the trace events from the tab's process (including all threads like compositor)
* * Sort those trace events in chronological order (as order isn't guaranteed)
* 4. Return all those items in one handy bundle.
Expand Down Expand Up @@ -835,7 +835,6 @@ class TraceProcessor {
firstPaint: frameTimings.timings.firstPaint,
firstContentfulPaint: frameTimings.timings.firstContentfulPaint,
firstContentfulPaintAllFrames: getTiming(fcpAllFramesEvt.ts),
firstMeaningfulPaint: frameTimings.timings.firstMeaningfulPaint,
largestContentfulPaint: frameTimings.timings.largestContentfulPaint,
largestContentfulPaintAllFrames: maybeGetTiming(lcpAllFramesEvt?.ts),
load: frameTimings.timings.load,
Expand All @@ -847,7 +846,6 @@ class TraceProcessor {
firstPaint: frameTimings.timestamps.firstPaint,
firstContentfulPaint: frameTimings.timestamps.firstContentfulPaint,
firstContentfulPaintAllFrames: fcpAllFramesEvt.ts,
firstMeaningfulPaint: frameTimings.timestamps.firstMeaningfulPaint,
largestContentfulPaint: frameTimings.timestamps.largestContentfulPaint,
largestContentfulPaintAllFrames: lcpAllFramesEvt?.ts,
load: frameTimings.timestamps.load,
Expand All @@ -857,12 +855,10 @@ class TraceProcessor {
firstPaintEvt: frameTimings.firstPaintEvt,
firstContentfulPaintEvt: frameTimings.firstContentfulPaintEvt,
firstContentfulPaintAllFramesEvt: fcpAllFramesEvt,
firstMeaningfulPaintEvt: frameTimings.firstMeaningfulPaintEvt,
largestContentfulPaintEvt: frameTimings.largestContentfulPaintEvt,
largestContentfulPaintAllFramesEvt: lcpAllFramesEvt,
loadEvt: frameTimings.loadEvt,
domContentLoadedEvt: frameTimings.domContentLoadedEvt,
fmpFellBack: frameTimings.fmpFellBack,
lcpInvalidated: frameTimings.lcpInvalidated,
};
}
Expand Down Expand Up @@ -970,28 +966,6 @@ class TraceProcessor {
throw this.createNoFirstContentfulPaintError();
}

// fMP will follow at/after the FP
let firstMeaningfulPaint = frameEvents.find(
e => e.name === 'firstMeaningfulPaint' && e.ts > timeOriginEvt.ts
);
let fmpFellBack = false;

// If there was no firstMeaningfulPaint event found in the trace, the network idle detection
// may have not been triggered before Lighthouse finished tracing.
// In this case, we'll use the last firstMeaningfulPaintCandidate we can find.
// However, if no candidates were found (a bogus trace, likely), we fail.
if (!firstMeaningfulPaint) {
const fmpCand = 'firstMeaningfulPaintCandidate';
fmpFellBack = true;
log.verbose('TraceProcessor',
`No firstMeaningfulPaint found, falling back to last ${fmpCand}`);
const lastCandidate = frameEvents.filter(e => e.name === fmpCand).pop();
if (!lastCandidate) {
log.verbose('TraceProcessor', 'No `firstMeaningfulPaintCandidate` events found in trace');
}
firstMeaningfulPaint = lastCandidate;
}

// This function accepts events spanning multiple frames, but this usage will only provide events from the main frame.
const lcpResult = this.computeValidLCPAllFrames(frameEvents, timeOriginEvt);

Expand All @@ -1007,7 +981,6 @@ class TraceProcessor {
timeOrigin: timeOriginEvt.ts,
firstPaint: getTimestamp(firstPaint),
firstContentfulPaint: firstContentfulPaint.ts,
firstMeaningfulPaint: getTimestamp(firstMeaningfulPaint),
largestContentfulPaint: getTimestamp(lcpResult.lcp),
load: getTimestamp(load),
domContentLoaded: getTimestamp(domContentLoaded),
Expand All @@ -1022,7 +995,6 @@ class TraceProcessor {
timeOrigin: 0,
firstPaint: maybeGetTiming(timestamps.firstPaint),
firstContentfulPaint: getTiming(timestamps.firstContentfulPaint),
firstMeaningfulPaint: maybeGetTiming(timestamps.firstMeaningfulPaint),
largestContentfulPaint: maybeGetTiming(timestamps.largestContentfulPaint),
load: maybeGetTiming(timestamps.load),
domContentLoaded: maybeGetTiming(timestamps.domContentLoaded),
Expand All @@ -1034,11 +1006,9 @@ class TraceProcessor {
timeOriginEvt: timeOriginEvt,
firstPaintEvt: firstPaint,
firstContentfulPaintEvt: firstContentfulPaint,
firstMeaningfulPaintEvt: firstMeaningfulPaint,
largestContentfulPaintEvt: lcpResult.lcp,
loadEvt: load,
domContentLoadedEvt: domContentLoaded,
fmpFellBack,
lcpInvalidated: lcpResult.invalidated,
};
}
Expand Down
Loading
Loading