Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: What is this devious Chrome throttling?
2 points by noduerme 27 days ago | hide | past | favorite | 6 comments
This is a question I wouldn't ask on S.O because no one would know what I was talking about. Here goes:

I'm messing around building a CPU pixel blitter, for fun. Here's a tiny demo:

https://thestrikeagency.com/ktest/dist/

I ran into lots of problems when I tried to run these draws on a setTimer, so I built a simple [actual, delta-based] timer.

If you watch it in Chrome, you'll see draws take ~5ms for the first 3 seconds, then throttle to 15ms for the next 50-60 seconds. Then all by themselves if you leave it running that long, they decide to go back to 5ms. If you background the window, it stays throttled for 50 seconds after you put the window in front.

I was aware of Event throttling and aware setTimer throttling. But this is running off Promises finished at the end of each iteration. (The code is unobfuscated if you want to look). Is Chrome throttling async/await ... based on user interaction?

Once Chrome decides I've kept it open for a full minute, it pegs at 60fps and doesn't drop again.

Does anyone know: What is this alchemy, and how can I prevent Chrome from throttling it for seconds 3 to 60 ?

[EDIT] VERY importantly: If you reload the tab, the throttling does not happen! It starts fast and stays fast after a reload. It only throttles if you close the tab and open it anew. Which is even weirder. Chrome remembers not to throttle a script after you reload it?!




Instead of `setTimeout` use `requestAnimationFrame`

Check out the code of this Lissajous Curve Demo https://ericfortis.github.io/lissajous/

This SO answer explains the difference: https://stackoverflow.com/a/38709924/529725


Very cool demo.

Sadly, though, the issue here is not in the time taken to request the new frame. I've built the loop to include a delta when each loop promise finishes, so the animation speed (motion across time) is stable. requestAnimationFrame would not help because the throttling is already accounted for; my code changes speed based on the framerate already.

The problem is that there's throttling happening in the array manipulation itself. This is why I have a "draw took" and "waited" time (ms) in the upper left: The "draw took" is how long it actually took to render the frame. "waited" is, the code waits the rest of the framerate to start the next frame, so at 60fps (1 framer per 16.6ms) if the frame took 5ms to render, the wait time after rendering would be 11.6ms.

What you can see is that "draw took" jumps up for no reason by 10ms after a few seconds of running the code, and then goes back down by 10ms after a minute of running the code. The draw itself - the rewriting of the screen buffer - takes longer because Chrome is throttling something which has nothing to do with the timer function itself. It's throttling something inside the array manipulation.


> requestAnimationFrame would not help

But have you tried it?


Yes. The same slowdown of about 50% occurs between about seconds 10 and 50 whether it's in a requestAnimationFrame loop or a setTimeout loop. And the slowdown is measurable in just the time it takes to modify a Uint8ClampedArray within the loop.



Have you considered garbage collection? Would fit the page reload thing. Just a thought.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: