$30 off During Our Annual Pro Sale. View Details »

Diagnosing INP & Breaking down long tasks

Nishu Goel
November 02, 2023

Diagnosing INP & Breaking down long tasks

Explores the pending Core Web Vital, Interaction to Next Paint that replaces FID in 2024 and diagnose it to solve pains with annoying long tasks in the browser, also using the Long Animation Frames API.

Nishu Goel

November 02, 2023
Tweet

More Decks by Nishu Goel

Other Decks in Programming

Transcript

  1. Breaking down long tasks

    View Slide

  2. Poor responsiveness/jankiness

    View Slide

  3. INP
    • Why replace FID?

    View Slide

  4. https://almanac.httparchive.org/en/2022/performance#fig-41

    View Slide

  5. gives you the worst interaction value, doesn’t
    tell you whats that worst interaction!

    View Slide

  6. Find the slow interactions
    - field data
    - lab data

    View Slide

  7. Field data
    • Pagespeed using CruX
    • Your RUM Provider
    • Web vitals JS library

    View Slide

  8. What to record?
    • INP value
    • Responsible element selector
    • Loading state at the point
    • Interaction start time
    • Event type (tap, click, keyboard event)

    View Slide

  9. https://app.datadoghq.eu/rum/performance-monitoring

    View Slide

  10. Not great INP value!
    RUM provider showed the bad INP value, but not the interaction
    causing it.

    View Slide

  11. Record using web vitals JS library
    (the attribution build)

    View Slide

  12. import { onINP } from 'web-vitals/attribution';

    View Slide

  13. View Slide

  14. View Slide

  15. View Slide

  16. Report the metrics collected to your analytics
    tool

    View Slide

  17. View Slide

  18. Have the field data, yayy! 🎉
    But, how to reproduce and fix?

    View Slide

  19. …comes testing in the lab

    View Slide

  20. Web vitals chrome extension

    View Slide

  21. View Slide

  22. Cannot use extensions? Mobile device?
    let worstInp = 0;
    const observer = new PerformanceObserver((list, obs, options) => {
    for (let entry of list.getEntries()) {
    if (!entry.interactionId) continue;
    entry.renderTime = entry.startTime + entry.duration;
    worstInp = Math.max(entry.duration, worstInp);
    console.log('[Interaction]', entry.duration, `type: ${entry.name}
    interactionCount: ${performance.interactionCount}, worstInp: ${worstInp}`, entry,
    options);
    }
    });
    observer.observe({
    type: 'event',
    durationThreshold: 0, // 16 minimum by spec
    buffered: true
    });

    View Slide

  23. View Slide

  24. Still no luck? Performance profile, here I come!

    View Slide

  25. View Slide

  26. View Slide

  27. - Input delays?
    - Expensive event callbacks?

    View Slide

  28. scheduler.yield()
    https://developer.chrome.com/origintrials/#/view_trial/836543630784069633

    View Slide

  29. startTransition() API

    View Slide

  30. rendering the updates can be the most challenging!
    (a.k.a presentation delay)

    View Slide

  31. Large DOM sizes
    Leads to Style recalculation

    View Slide

  32. Forced reflows – CSS selector complexity
    .box:nth-last-child(-n+1) .title {
    /* styles */
    }
    https://web.dev/articles/reduce-the-scope-and-complexity-of-style-calculations

    View Slide

  33. Long tasks API
    • Tells you a long task happened and took this long, but doesn't tell
    what might have caused it. – Basic attribution model
    • Doesn't count the rendering updates time, happens in a different
    task.

    View Slide

  34. Long Animation frames
    observer.observe({ type: 'long-animation-frame', buffered: true });

    View Slide

  35. • Name
    • Event type
    • Timing data
    • Window attribution etc.
    Better attribution
    https://developer.chrome.com/articles/long-animation-frames/

    View Slide

  36. chrome://flags/#enable-experimental-web-platform-features

    View Slide

  37. Origin trials for LoAF
    https://developer.chrome.com/origintrials/#/view_trial/3935020174414970881

    View Slide

  38. View Slide

  39. Strategies to yield to the main thread

    View Slide

  40. View Slide

  41. Deferred events pushed to the end of the queue?

    View Slide

  42. scheduler
    .yield()
    developer.chrome.com/origintrials

    View Slide

  43. View Slide

  44. Scheduler
    .postTask()

    View Slide

  45. scheduler
    .postTask(method, {priority: ‘user-blocking’ })
    scheduler
    .postTask(method, {priority: ‘user-visible’ })
    scheduler
    .postTask(method, {priority: ‘background’ })

    View Slide

  46. navigator.scheduling.isInputPending()

    View Slide

  47. View Slide

  48. Quick recap:
    • INP – pending CWV for March 2024
    • Gives good attribution data to diagnose
    • Leads you to measure field data using web vitals JS library for example
    • We should then use lab tools to reproduce the slowness
    • Understanding delays in the browser
    • Strategies to fix the main thread blocking.

    View Slide

  49. thank you!
    x.com/TheNishuGoel

    View Slide