-
-
Save radum/e8aadc5b120160e7d42b12fba3fd6f3f to your computer and use it in GitHub Desktop.
Monitoring Jank Example
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
// From here https://gist.github.com/l8on/7378d518a001a87adaf42a00fb7e50be#file-monitoring-jank-coffee | |
// https://fulcrum.lever.co/monitoring-jank-how-we-found-the-slowest-parts-of-our-ui-b6ffd7386896 | |
var isModernBrowser, isNative, setupJankTracking; | |
// Simple function that uses a heuristic to tell if a function | |
// is native code. Luckily this isn't security related code. | |
isNative = function(fn) { | |
return /\{\s*\[native code\]\s*\}/.test("" + fn); | |
}; | |
// An easy check to ensure we are on a modern browser | |
isModernBrowser = function() { | |
var ref; | |
return ( | |
window.addEventListener && | |
((ref = window.performance) != null ? ref.now : void 0) && | |
isNative(window.requestAnimationFrame) | |
); | |
}; | |
// Do nothing if this is not a modern browser | |
if (!isModernBrowser()) { | |
return; | |
} | |
// Wait for the application to finish loading before setting up jank tracking. | |
window.addEventListener("load", setupJankTracking); | |
setupJankTracking = function() { | |
var EXPECTED_RAF_DURATION, | |
JANK_THRESHOLD, | |
MAX_DEPTH, | |
generateQuerySelector, | |
jankState, | |
onAnimationFrame, | |
onEvent, | |
trackJank; | |
// Browsers call back to `requestAnimationFrame` 60 times per second | |
// under smooth rendering conditions. | |
EXPECTED_RAF_DURATION = 1000.0 / 60.0; | |
// Only report jank if it is over this threshold | |
JANK_THRESHOLD = { | |
A_REASONABLE_THRESHOLD_FOR_YOUR_APP: A_REASONABLE_THRESHOLD_FOR_YOUR_APP | |
}; | |
// Create state in shared scope | |
jankState = { | |
event: null, | |
location: null, | |
timerStart: null | |
}; | |
onEvent = function(event) { | |
var ref; | |
// Only track one event at a time. | |
if (jankState.event) { | |
return; | |
} | |
jankState.event = event; | |
jankState.location = window.location.href; | |
jankState.timerStart = (ref = window.performance) != null | |
? ref.now() | |
: void 0; | |
return window.requestAnimationFrame(onAnimationFrame); | |
}; | |
onAnimationFrame = function() { | |
var jankAmount; | |
// This can be negative as the next frame is not always 16ms away. | |
jankAmount = | |
window.performance.now() - | |
jankState.timerStart - | |
EXPECTED_RAF_DURATION; | |
// Some amount of jank is OK and mostly unnoticeable. | |
// Limit tracking to the out of the ordinary | |
if (jankAmount > JANK_THRESHOLD) { | |
trackJank(jankAmount); | |
} | |
// Reset jankState so we capture the next event | |
jankState.event = null; | |
jankState.location = null; | |
return (jankState.timerStart = null); | |
}; | |
trackJank = function(jankAmount) { | |
// Ideally, your tracking infrastructure queues things up for the | |
// next event loop and doesn't block rendering. | |
return window.monitoring.track({ | |
jankAmount: jankAmount, | |
querySelector: generateQuerySelector(), | |
locationChanged: window.location.href !== jankState.location | |
}); | |
}; | |
MAX_DEPTH = { | |
A_REASONABLE_DEPTH_FOR_YOUR_APP: A_REASONABLE_DEPTH_FOR_YOUR_APP | |
}; | |
generateQuerySelector = function() { | |
// Watch out for synthetic events that don't have a target! | |
var querySelector; | |
if (!jankState.event.target) { | |
return ""; | |
} | |
// You can imagine what traverseUpDOMTree would look like ;) | |
querySelector = traverseUpDOMTree(MAX_DEPTH); | |
return querySelector; | |
}; | |
// We use event capturing here (the third param) to set up jank | |
// monitoring before standard event handlers do their work. | |
// Also, we attach to the window so the event listeners are not | |
// destroyed on navigation. | |
window.addEventListener("click", onEvent, true); | |
return window.addEventListener("keydown", onEvent, true); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment