From 77f635eec45ba3e4c8f58dc8669c313add41373a Mon Sep 17 00:00:00 2001 From: soulgalore Date: Fri, 14 Jul 2023 18:47:13 +0200 Subject: [PATCH 1/2] Get elements that needs recalculate styles before FCP/LCP. First go at collecting number of elements that needs recalculate styles before FCP/LCP. I think this should work fine, the only thing that needs tweaking is the data structure. --- lib/chrome/webdriver/chromium.js | 26 +++++++++++ lib/chrome/webdriver/traceUtilities.js | 64 ++++++++++++++++++++++++++ lib/core/engine/collector.js | 8 ++++ 3 files changed, 98 insertions(+) create mode 100644 lib/chrome/webdriver/traceUtilities.js diff --git a/lib/chrome/webdriver/chromium.js b/lib/chrome/webdriver/chromium.js index b9e5e15c7..0a0c77af6 100644 --- a/lib/chrome/webdriver/chromium.js +++ b/lib/chrome/webdriver/chromium.js @@ -15,6 +15,11 @@ import { parse } from '../traceCategoriesParser.js'; import { pathToFolder } from '../../support/pathToFolder.js'; import { ChromeDevtoolsProtocol } from '../chromeDevtoolsProtocol.js'; import { Android, isAndroidConfigured } from '../../android/index.js'; +import { + getFirstContentFulPaintEvent, + getLargestContentfulPaintEvent, + getRecalculateStyleElementsAndTimeBefore +} from './traceUtilities.js'; const unlink = promisify(_unlink); const rm = promisify(_rm); @@ -353,6 +358,27 @@ export class Chromium { asset.args.data.renderBlocking; } + const fcpEvent = getFirstContentFulPaintEvent(trace.traceEvents); + const lcpEvent = getLargestContentfulPaintEvent(trace.traceEvents); + + result.renderInformation = { recalculateStyle: {} }; + + if (fcpEvent) { + const beforeFCP = getRecalculateStyleElementsAndTimeBefore( + trace.traceEvents, + fcpEvent.ts + ); + result.renderInformation.recalculateStyle.beforeFCP = beforeFCP; + } + + if (lcpEvent) { + const beforeLCP = getRecalculateStyleElementsAndTimeBefore( + trace.traceEvents, + lcpEvent.ts + ); + result.renderInformation.recalculateStyle.beforeLCP = beforeLCP; + } + if (!this.options.skipHar) { for (let harRequest of this.hars[index - 1].log.entries) { if (renderBlockingInfo[harRequest.request.url]) { diff --git a/lib/chrome/webdriver/traceUtilities.js b/lib/chrome/webdriver/traceUtilities.js new file mode 100644 index 000000000..2ca1c8022 --- /dev/null +++ b/lib/chrome/webdriver/traceUtilities.js @@ -0,0 +1,64 @@ +import intel from 'intel'; +const log = intel.getLogger('browsertime.chrome'); + +export function getLargestContentfulPaintEvent(traceEvents) { + const lcpCandidates = traceEvents.filter( + task => task.name === 'largestContentfulPaint::Candidate' + ); + + if (lcpCandidates.length > 0) { + let lcpEvent = lcpCandidates[0]; + + for (const candidate of lcpCandidates) { + if (candidate.ts > lcpEvent.ts) { + lcpEvent = candidate; + } + } + return lcpEvent; + } else { + log.info('No LCP event found in the trace'); + } +} + +export function getFirstContentFulPaintEvent(traceEvents) { + // Get first contentful paint + const fcpEvent = traceEvents.find( + task => task.name === 'firstContentfulPaint' + ); + + if (fcpEvent) { + return fcpEvent; + } else { + log.info('Did not find the FCP event in the trace'); + } +} + +export function getRecalculateStyleElementsAndTimeBefore( + traceEvents, + timestamp +) { + const recalculatesBefore = traceEvents.filter( + task => + task.cat === 'disabled-by-default-devtools.timeline' && + task.name === 'ScheduleStyleRecalculation' && + task.ts < timestamp + ); + + const updateLayoutTree = traceEvents.filter( + task => + task.cat === 'blink,devtools.timeline' && + task.name === 'UpdateLayoutTree' && + task.ts < timestamp && + recalculatesBefore.some( + recalculate => task.args.beginData.frame === recalculate.args.data.frame + ) + ); + let elements = 0; + let duration = 0; + for (let a of updateLayoutTree) { + elements += a.args.elementCount; + duration += a.dur; + } + + return { elements, durationInMillis: duration / 1000 }; +} diff --git a/lib/core/engine/collector.js b/lib/core/engine/collector.js index 21f9dd9e0..51e26b822 100644 --- a/lib/core/engine/collector.js +++ b/lib/core/engine/collector.js @@ -48,6 +48,7 @@ function getNewResult(url, options) { cpu: [], googleWebVitals: [], extras: [], + renderInformation: [], fullyLoaded: [], mainDocumentTimings: [], errors: [], @@ -399,6 +400,13 @@ export class Collector { }); } + if (data.renderInformation) { + results.renderInformation.push(data.renderInformation); + statistics.addDeep({ + renderInformation: data.renderInformation + }); + } + if (data.renderBlocking) { if (!results.renderBlocking) { results.renderBlocking = []; From ce362cff0a9b30438102d7c6fe53b5725ae1b54b Mon Sep 17 00:00:00 2001 From: soulgalore Date: Sat, 15 Jul 2023 08:18:04 +0200 Subject: [PATCH 2/2] Add the data in renderBlocking instead --- lib/chrome/webdriver/chromium.js | 8 ++++---- lib/core/engine/collector.js | 14 ++++++-------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/chrome/webdriver/chromium.js b/lib/chrome/webdriver/chromium.js index 0a0c77af6..74ac019c3 100644 --- a/lib/chrome/webdriver/chromium.js +++ b/lib/chrome/webdriver/chromium.js @@ -361,14 +361,14 @@ export class Chromium { const fcpEvent = getFirstContentFulPaintEvent(trace.traceEvents); const lcpEvent = getLargestContentfulPaintEvent(trace.traceEvents); - result.renderInformation = { recalculateStyle: {} }; + result.renderBlocking = { recalculateStyle: {}, requests: {} }; if (fcpEvent) { const beforeFCP = getRecalculateStyleElementsAndTimeBefore( trace.traceEvents, fcpEvent.ts ); - result.renderInformation.recalculateStyle.beforeFCP = beforeFCP; + result.renderBlocking.recalculateStyle.beforeFCP = beforeFCP; } if (lcpEvent) { @@ -376,7 +376,7 @@ export class Chromium { trace.traceEvents, lcpEvent.ts ); - result.renderInformation.recalculateStyle.beforeLCP = beforeLCP; + result.renderBlocking.recalculateStyle.beforeLCP = beforeLCP; } if (!this.options.skipHar) { @@ -388,7 +388,7 @@ export class Chromium { } } - result.renderBlocking = renderBlockingInfo; + result.renderBlocking.requests = renderBlockingInfo; } // Google Web Vitals hacksery diff --git a/lib/core/engine/collector.js b/lib/core/engine/collector.js index 51e26b822..29c301694 100644 --- a/lib/core/engine/collector.js +++ b/lib/core/engine/collector.js @@ -48,7 +48,6 @@ function getNewResult(url, options) { cpu: [], googleWebVitals: [], extras: [], - renderInformation: [], fullyLoaded: [], mainDocumentTimings: [], errors: [], @@ -400,18 +399,17 @@ export class Collector { }); } - if (data.renderInformation) { - results.renderInformation.push(data.renderInformation); - statistics.addDeep({ - renderInformation: data.renderInformation - }); - } - if (data.renderBlocking) { if (!results.renderBlocking) { results.renderBlocking = []; } results.renderBlocking.push(data.renderBlocking); + + statistics.addDeep({ + renderBlocking: { + recalculateStyle: data.renderBlocking.recalculateStyle + } + }); } // Add power data (if we have it)