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

LoAF Summary attribution information #574

Open
wants to merge 25 commits into
base: v5
Choose a base branch
from
Open

LoAF Summary attribution information #574

wants to merge 25 commits into from

Conversation

tunetheweb
Copy link
Member

@tunetheweb tunetheweb commented Dec 6, 2024

Fixes #559

Includes object like this:

"longAnimationFrameSummary": {
    "numLongAnimationFrames": 3,
    "numIntersectingScripts": 9,
    "slowestScript": {
      "entry": // Not Shown,
      "subpart": "processingDuration",
      "intersectingDuration": 395,
      "totalDuration": 395,
      "compileDuration": 0,
      "executionDuration": 395,
      "forcedStyleAndLayoutDuration": 144,
      "pauseDuration": 0,
      "invokerType": "event-listener",
      "invoker": "BUTTON.onclick",
      "sourceURL": "",
      "sourceFunctionName": "",
      "sourceCharPosition": -1,
    },
    "totalDurationsPerSubpart": {
        "inputDelay": {
            "user-callback": 28,
            "event-listener": 185
        },
        "processingDuration": {
            "event-listener": 434
        }
    },
    "totalForcedStyleAndLayoutDuration": 144,
    "totalNonForcedStyleAndLayoutDuration": 3144099.700000003,
    "totalScriptDuration": 647
}

Copy link
Member

@rviscomi rviscomi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Barry! Left a few comments.

README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
}
totalScriptTime += script.duration;
numScripts++;
totalForcedStyleAndLayout += script.forcedStyleAndLayoutDuration;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's an open question whether we should only be taking the blocking/intersecting portion of all duration metrics. WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately we can't for forced style and layout since we don't have the timings LoAF. Maybe that's a good reason to keep this simple and just take it for all intersecting scripts (which is what it does currently)?

src/attribution/onINP.ts Outdated Show resolved Hide resolved
src/attribution/onINP.ts Outdated Show resolved Hide resolved
src/attribution/onINP.ts Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
Copy link
Member

@brendankenny brendankenny left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

incidentally, it seems like we're leaning subparts, not phases for LCP, so we might want to do the same thing here (or object quickly on the LCP side of things :)

src/types/inp.ts Outdated Show resolved Hide resolved
src/attribution/onINP.ts Outdated Show resolved Hide resolved
src/attribution/onINP.ts Outdated Show resolved Hide resolved
src/attribution/onINP.ts Outdated Show resolved Hide resolved
src/attribution/onINP.ts Outdated Show resolved Hide resolved
src/attribution/onINP.ts Outdated Show resolved Hide resolved
src/attribution/onINP.ts Outdated Show resolved Hide resolved
@tunetheweb
Copy link
Member Author

incidentally, it seems like we're leaning subparts, not phases for LCP, so we might want to do the same thing here (or object quickly on the LCP side of things :)

I'm cool with subparts so switched to that throughout.

@tunetheweb
Copy link
Member Author

@rviscomi I've flattened the structure, and updated the comment in #574 (comment) to show that.

Copy link
Member

@rviscomi rviscomi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! I'll try it out in the next RC.

* NOTE: This may be be less than the total count of scripts in the Long
* Animation Frames as some scripts may occur before the interaction.
*/
numIntersectingScripts: number;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather that just listing the number of intersecting scripts, I wonder if it would be more useful to create an array of intersecting scripts (which then someone could easily call .length on).

Related, how common is it for scripts from multiple different LoAF entries to all be intersecting with INP?

/**
* The number of Long Animation Frames intersecting the INP interaction.
*/
numLongAnimationFrames: number;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems unnecessary because someone could easily do longAnimationFrameEntries.length, right?

/**
* The INP sub-part where the longest script ran.
*/
subpart: INPSubpart; //'inputDelay' | 'processingDuration' | 'presentationDelay';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On web.dev these are currently referred to as "phases". Are we planning to change that?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brendankenny I think it was you that told me were were moving towards subparts to mirror LCP, is that right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we should definitely unify. I suggested it specifically because we didn't want to simultaneously cement "phases" here in web-vitals and "subparts" over in CrUX, and everyone in the LCP discussions agreed on "subpart".

/**
* The INP sub-part where the longest script ran.
*/
subpart: INPSubpart; //'inputDelay' | 'processingDuration' | 'presentationDelay';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
subpart: INPSubpart; //'inputDelay' | 'processingDuration' | 'presentationDelay';
subpart: INPSubpart; // 'input-delay' | 'processing-duration' | 'presentation-delay'

For consistency with other enum-type options.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is interesting. Yes as an enum they should use that format. However this is then exposed in output—as both property names and values:

      "slowestScript": {
...
        "subpart": "processingDuration",
        "intersectingDuration": 100,
...
      },
      "totalDurationsPerSubpart": {
        "processingDuration": {
          "event-listener": 100
        }
      },

And so they should really follow camelCase? Though the invoker type is hyphenated (and that's part of the spec) so it's a little inconsistent anyway in that regards

The other consideration is that camelCase is also consistent with what we use for LCP sub parts, but there they are strict property names (not values) and we don't have them defined as an enum.

* The slowest Long Animation Frame script that intersects the INP
* interaction.
*/
slowestScript: SlowestScriptSummary;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now the SlowestScriptSummary object duplicates many of the native PerformanceScriptTiming properties, and it's not clear to me how valuable that is. AFAICT the only "computed" values are subpart and intersectingDuration.

What if instead we just had three top-level attribution properties?

  • slowestScriptEntry
  • slowestScriptPhase (or subpart)
  • slowestScriptIntersectingDuration

src/attribution/onINP.ts Outdated Show resolved Hide resolved
@@ -24,6 +24,140 @@ export interface INPMetric extends Metric {
entries: PerformanceEventTiming[];
}

export type INPSubpart =
| 'inputDelay'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| 'inputDelay'
| 'input-delay'

@@ -24,6 +24,140 @@ export interface INPMetric extends Metric {
entries: PerformanceEventTiming[];
}

export type INPSubpart =
| 'inputDelay'
| 'processingDuration'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| 'processingDuration'
| 'processing-duration'

export type INPSubpart =
| 'inputDelay'
| 'processingDuration'
| 'presentationDelay';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| 'presentationDelay';
| 'presentation-delay';

/**
* The INP sub-part where the longest script ran.
*/
subpart: INPSubpart; //'inputDelay' | 'processingDuration' | 'presentationDelay';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
subpart: INPSubpart; //'inputDelay' | 'processingDuration' | 'presentationDelay';
subpart: INPSubpart; // 'input-delay' | 'processing-duration' | 'presentation-delay'

* The slowest Long Animation Frame script that intersects the INP
* interaction.
*/
slowestScript: SlowestScriptSummary;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I wonder if longestScript would be better and more consistent with other API names (e.g. Long Tasks and Long Animation Frames).

subpart: slowestScriptSubpart,
intersectingDuration: slowestScriptDuration,
totalDuration: slowestScriptEntry?.duration,
compileDuration:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the ?. optional chaining operator here seems risky because if slowestScriptEntry is undefined then you'll end up doing math operations on undefined, which will result in NaN.

I know there's been some discussion of removing these properties anyway, but if we don't then it's probably better to just omit these (or set them to 0) if there's no slowest script.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants