Last active
May 28, 2024 17:20
-
-
Save noamr/316bd48157ab35e4f632a8c2583281b7 to your computer and use it in GitHub Desktop.
WhyNP: Analyze LoAFs & event timing entries to find cause of bad INP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function() { | |
let pending_loaf_entries = []; | |
let pending_event_entries = []; | |
let timeout_handle = null; | |
const combined_map = new Map(); | |
function print() { | |
const entries = [...combined_map.entries()].sort((a, b) => b.duration - a.duration); | |
console.log(entries.map(([loaf, event]) => { | |
let longest_script = null; | |
let total_thrashing_duration = 0; | |
for (const script of loaf.scripts) { | |
total_thrashing_duration += script.forcedStyleAndLayoutDuration; | |
if (script.duration > (longest_script?.duration ?? 0)) | |
longest_script = script; | |
} | |
return { | |
loaf_blocking_duration: loaf.blockingDuration, | |
event_duration: event.duration, | |
longest_script, | |
total_thrashing_duration, | |
render_time: (loaf.startTime + loaf.duration - loaf.renderStart), | |
loaf, event | |
}; | |
})); | |
} | |
function process() { | |
for (const event_entry of pending_event_entries) { | |
for (const loaf_entry of pending_loaf_entries) { | |
if (!loaf_entry.blockingDuration) | |
continue; | |
/* This LoAF ends before this event starts.*/ | |
if ((loaf_entry.startTime + loaf_entry.duration) < event_entry.startTime) | |
continue; | |
/* This LoAF starts after this event ends. */ | |
if (loaf_entry.startTime > (event_entry.startTime + event_entry.duration)) | |
break; | |
if (event_entry.duration > (combined_map.get(loaf_entry)?.duration ?? 0)) | |
combined_map.set(loaf_entry, event_entry); | |
} | |
} | |
pending_loaf_entries = []; | |
pending_event_entries = []; | |
print(); | |
} | |
function schedule_process() { | |
// Debounce, to make sure all the relevant entries are in. | |
if (timeout_handle) | |
clearTimeout(timeout_handle); | |
timeout_handle = setTimeout(() => { | |
timeout_handle = null; | |
process(); | |
}, 1000); | |
} | |
new PerformanceObserver(entries => { | |
pending_loaf_entries = [...pending_loaf_entries, ...entries.getEntries()]; | |
}).observe({type: "long-animation-frame", buffered: true}); | |
new PerformanceObserver(entries => { | |
const unique_entries = Object.values(Object.fromEntries(entries.getEntries().map(entry => [JSON.stringify(entry), entry]))); | |
pending_event_entries = [...pending_event_entries, ...unique_entries]; | |
schedule_process(); | |
}).observe({type: "event", buffered: true, durationThreshold: 150}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@noamr Sorry for the delayed ping :/