Skip to content

Instantly share code, notes, and snippets.

@mattgperry
Last active January 13, 2024 16:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattgperry/454158ed97d5abeb3f4ed511264cbb64 to your computer and use it in GitHub Desktop.
Save mattgperry/454158ed97d5abeb3f4ed511264cbb64 to your computer and use it in GitHub Desktop.
Pre-generated keyframes performance issues in Chrome
<html>
<head>
<title>Pre-generated keyframes performance</title>
<!--
This file demonstrates that the performance of pre-generated keyframes is poor in Chrome
under surprising circumstances.
Specifically, pre-generated keyframes are fine in isolation. But when combined with a
requestAnimationFrame animation, AND another WAAPI animation, performance becomes
(literally) 100x worse.
To use:
1. Open this file in Chrome
2. Open performance tab and throttle 6x
3. On an M1 Pro notice style recalculations of ~170ms
4. Comment `animation.ready` block, disabling requestAnimationFrame animation
5. Profile and notice style recalculations of ~1.5ms
6. Undo changes
7. Comment out `opacity` WAAPI animation, moving `const animation = ` to background-color animation.
8. Profile and notice style recalculations of ~2.5ms
9. Undo changes
10. Replace `backgroundColor: pregeneratedKeyframes` with `backgroundColor: ["#f00", "#00f"]`
11. Profile and notice style recalculations of ~2.5ms
-->
<style>
body {
display: flex;
flex-wrap: wrap;
gap: 10px;
height: 100vh;
overflow: hidden;
}
.box {
width: 100px;
height: 100px;
background-color: #f00;
opacity: 0;
}
</style>
</head>
<body>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<script>
const boxes = document.querySelectorAll(".box");
let startTime = 0;
const duration = 10000;
const rotateRate = 360 / duration;
function rotate(timestamp) {
const elapsed = timestamp - startTime;
boxes.forEach((box, index) => {
box.style.transform = `rotate(${elapsed * rotateRate}deg)`;
});
requestAnimationFrame(rotate);
}
function animateRotation() {
startTime = performance.now();
requestAnimationFrame(rotate);
}
const pregeneratedKeyframes = [];
const mixLinearColor = (from, to, p) => {
const fromExpo = from * from;
return Math.sqrt(Math.max(0, p * (to * to - fromExpo) + fromExpo));
};
for (let i = 0; i < 1000; i++) {
const p = i / 1000;
const r = Math.floor(mixLinearColor(255, 0, p));
const g = 0;
const b = Math.floor(mixLinearColor(0, 255, p));
pregeneratedKeyframes.push(`rgb(${r}, ${g}, ${b})`);
}
boxes.forEach((box, index) => {
const animation = box.animate(
{ opacity: [0, 1] },
{ duration, iterations: Infinity }
);
box.animate(
{ backgroundColor: pregeneratedKeyframes },
{ duration, iterations: Infinity }
);
if (!index) {
animation.ready.then(() => {
animateRotation();
});
}
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment