I recently noticed that animations in Safari were stuttering pretty badly on my M1 powered 2020 MacBook Air, and dove in to figure out why.
I’m a web developer, so I went to work writing a small bit of vanilla JavaScript to monitor requestAnimationFrame
which is the API that the window object uses to “paint” its contents to the screen. (I did a ton of research to make sure, and it’s pretty neat.)
Both Chrome and Firefox were showing 60 frames per second as expected, but Safari was only showing as 30. 🧐
Isn’t Safari… like… supposed to be better? Something something own-the-stack? Meow meow top-down-integration, King Friday? 👑
I was pretty confused by Safari being worse here, so I tweaked my JavaScript a bunch, searched the web for clues, and walked away from the problem for a few days, but didn’t learn anything helpful or have any epiphanies.
Then one random Tuesday, Safari started running at 60fps again. Huh. Hmm.
I restarted. I opened & closed a variety of different apps. I closed a bunch of tabs everywhere. I updated all-of-the-things.
I couldn’t make Safari slow again even when I tried.
It made no sense. But hey… it’s fixed. Yay.
The next morning I started worky mcworkface and Safari was back down to 30fps.
GAH! OK. OK. OK.
“What variables changed” I thought – “What did I do differently?”
I was on battery power when it was 30.
I was plugged in when it was 60.
Holy 🎅🏻💩… a reproducible result…
Plugged in: 60. Unplugged: 30. Plugged in: 60. Unplugged: 30.
🐢🐢🐢🐇🐇🐇
This wasn’t a bug. This was a feature.
System Preferences > Battery > Battery > Low power mode
By default, macOS Monterey enables “Low power mode” on Battery power and disables it when using a Power Adapter. Safari, it seems, is programmed to interpret this setting to mean that it should reduce the number of times it paints to the screen to prolong battery life.
On my MacBook Air, that means from 60fps to 30fps.
What does it mean on a 2021 MacBook Pro with ProMotion, at 120fps?
Unclear… because I don’t own one, yet… but my thinking is: folks noticing stuttering in Safari on their beefy new machines are seeing this happen how I just did, and if they disable Low power mode it will jump back up to 120fps.
The built-in display on my MacBook Air does not have a variable refresh rate. I’m not sure what it tops out at because Apple goes to great lengths to hide this information these days, but my guess is it’s running at around 60hz.
My final theories about Safari stuttering on 2021 MacBooks with 120hz ProMotion displays, is that the requestAnimationFrame
API might be dropping all the way down to 10fps to match the 10hz floor of ProMotion – or it may not be perfectly synced up with the refresh rate, resulting in a sort of double-jitter problem.
If the API slows down to 10fps but the display ramps up from 10hz to 60hz, you’d certainly feel like Safari was not performing very well, especially compared to Chrome & Firefox that never slow down.
If I learn anything new, I’ll update this post!