three.js: requestAnimationFrame loop causes CPU hog
Followup to issue #642
I’ve followed the tutorial that suggested to call requestAnimationFrame() and render in a loop:
function render() {
requestAnimationFrame( render );
renderer.render( scene, camera );
}
render();
This bug caused my page to hog 1-2 CPU cores - 100% CPU usage on these cores - forever, even if nothing at all is happening in the scene, as long as my webpage was open, for days. It drains battery, uses electricity needlessly, and spins up fans. Thus, causing noise pollution and indirectly environmental pollution. Needless to say, that’s a (page) killer. I was so frustrated, I was seriously trying to rewrite everything using another 3D library. (SceneJS doesn’t seem to have the same problem.)
I think this needs to be fixed in ThreeJS. If nothing else, to save all our CPU cores on all the pages that use ThreeJS.
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Comments: 23 (6 by maintainers)
Sorry, but this is clearly still an issue. No webpage should continue to use 100% CPU forever. But all the ThreeJS examples do that. Most developers will just copy that and waste CPU. Instead, ThreeJS should use 1) only minimal (as little as possible) CPU power even with an animation, and 2) no CPU at all when there are no changes. This is easy to do with e.g. a dirty flag.
WestLangley:
I already answered that in comment 1: Because that’s what the tutorial said. I followed the tutorial, which is what any reasonable developer will do when he starts using a library he doesn’t know. There was no hint whatsoever that the render should be conditional on anything. That’s the purpose of a tutorial, to teach this.
Huh? That’s what I’m doing? That’s what I wrote in comment 2? What’s your point?
My point is that this needs to be fixed in ThreeJS, or at the very least in the tutorial and the examples need to be fixed.
I found a good way by watching only state changes if you’re using React. The following sample code will stop the render animation loop if current status is not in running state. Since any state changes will trigger
componentDidUpdate
when the component has been updated, it seemscomponentDidUpdate
is a good place to callrequestAnimationFrame
to restart the loop.@benbucksch said
Why are you calling
requestAnimationFrame
if you have a static scene? Just render once in response to user events.My guess is that using just event listeners only works for 20% of the projects.
@mrdoob : Would it be possible to update the tutorials, sample code and README, to reflect the above changes?
I choose ThreeJS because of control is on you. Maybe some game engines do this and some caching by default. Using your solution is good for some article about optimisations. Thanks for your code as an inspiration. In my case animations may stop only in “sugar spot” destinations. ThreeJS is simple enough to start building the stuff and tweak it slowly to what I want. Maybe because it is rendering engine, not game one. Other JS game engines were not offering this detailed customisation.
The bug here was: The lib should do this by default. Or at least the sample code should demonstrate this, as every developer needs that. It’s never OK to hog the CPU like that.
That is correct. WebWorkers were created for that, but they have no UI access.
However, that fact is not related to this bug report. See my last comment (from about 5 years ago, sadly). Using 100% CPU forever is bad, on any core. The sample code is teaching developers to do the wrong thing.