Why does scrolling trigger lag in onFrame()?

What would cause a React Re-Rendering of functional components inside of react-three fiber?

It seems like a memory issue.

The above is a performance graph.
The spikes occur when I scroll up or down during animation.

No scrolling handler present.

What could the spikes mean?

Thanks.

That’s literally a screenshot :face_with_hand_over_mouth:

That’s a typical GC behaviour with those spikes but it can be better if libraries wouldn’t keep creating objects, especially in animation loops it is a nogo.

React is quite bulky and often tends to cause some bad performance or high memory usage, it is quite easy to get something to become a bottleneck, however it would be good to demonstrate your issue in a live example with codepen or jsfiddle as it’s hard to guess from a screenshot - if you actually have a perfomance problem and aren’t just worried about the GC intervals, if they are huge you will experience hickups.

What is a GC?

Garbage collector, basically collecting unreferenced unused js objects to release the memory, we don’t have control over it in browsers so it’s a good idea to not cause a lot garbage that will flushed down the sink so the drain get’s clogged a little causing perfromance hickups, if it’s clogged fully (massively spawning objects in a animation loop) the page might die.

What is the most efficient method to define variables such that they don’t go through the garbage collector?

My understanding is the scroll up and down causes a re-render due to flushing garbage. After garbage is flushed, object position is changed further causing me to think it’s GC that’s reducing efficiency.

How do I approach solving such a problem?

Object pooling and reusing objects like spawning them in a higher scope/closure that doesn’t create that object in the function everytime.

Scrolling does cause a redraw and reflow at least of the scrolling container but that doesn’t relate to JS garbage directly, i don’t see your code or plugins you possibly used neither what react does specifially, there could be a event listener you can look for in devtools that causes a lot garbage, just record a bit of scrolling and investigate or profile memory.

1 Like

The biggest culprit of garbage accumulation I’ve seen is devs initiating single-use objects on each frame, instead of reusing the same one:

// Wrong
onUpdate() {
	var position = new THREE.Vector3(x, y, z);
	requestAnimationFrame(onUpdate);
}

// Right
var position = new THREE.Vector3();
onUpdate() {
	position.set(x, y, z);
	requestAnimationFrame(onUpdate);
}
2 Likes

in react-three-fiber rendering is happening outside of react. react itself basically just manages the scene and there should be no performance overhead. the memory it uses is insignificant.

now, everything you put inside onFrame runs in a combined requestAnimationLoop, if you notice laggy behaviour that could either be what the others say, you should be re-pooling objects, or, and that you should never do, you are somehow causing updates like calling setState inside useFrame. that would be bad.

i’ve written about this here: react-three-fiber/pitfalls.md at 8101d468bc4a137056f665d4d868056e301c1cad · pmndrs/react-three-fiber · GitHub

and check out these guidelines, they are wonderful, written by @looeee: https://discoverthreejs.com/tips-and-tricks

a codesandbox would make it easier to help you. all you need to do is type npx codesandbox . and it creates one from your local project.

1 Like