How to improve performance of updating many objects (e.g. 500) in an array? #1188
-
|
I'm building an infinite canvas app similar to tldraw or Excalidraw. I chose valtio to manage the canvas state because its automatic render optimization and easy-to-use mutation pattern help me build quickly. I noticed a performance issue recently: when users select and drag multiple objects, the frame rate drops as the number of selected objects increases. While debugging with the browser's Performance tool, I found that valtio was taking up most of the time during slow frames. Here's a simplified version of my code that updates the positions of multiple objects when dragging: import { proxy, subscribe, snapshot } from 'valtio/vanilla';
const canvas = proxy({
nodes: new Array(500).fill({ x: 100, y: 100, text: 'hello' }),
});
console.log('init canvas', snapshot(canvas));
subscribe(canvas, () => {
console.log('canvas updated', snapshot(canvas));
});
function updateCanvas() {
canvas.nodes.forEach((node) => {
node.x += 1;
node.y += 1;
});
}
window.addEventListener('mousemove', updateCanvas);When running this code in Chromium 143.0.7499.40 on a MacBook Air M1 plugged into the wall, I found that updating more than 500 objects at once causes valtio's scripting time to exceed 16ms per frame. This means the frame rate drops below 60fps when trying to render, which isn't ideal. In a graphics-intensive app, 500 objects feels like a small number. Most apps need to handle thousands of objects smoothly. So, I’m wondering if there's any way to improve performance in both valtio and the way I’m using it for this scenario. For convenience, I prepared an online dev environment demonstrating the issue: https://stackblitz.com/edit/valtio-stress-test?file=index.html,src%2Fmain.ts |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 3 replies
-
|
Thanks for reporting. What I notice is that the behavior is the same even if we comment out https://stackblitz.com/edit/valtio-stress-test-urmfzyvj?file=index.html,src%2Fmain.ts |
Beta Was this translation helpful? Give feedback.
-
|
Only
https://stackblitz.com/edit/valtio-stress-test-q6aj68ug?file=package.json,src%2Fmain.ts To support adding, removing, and reordering nodes, we can use a string array proxy with node IDs. This works because when rendering a list, we usually only need the IDs. We can pass these IDs to the components that render the nodes, and each component will fetch its corresponding node proxy. |
Beta Was this translation helpful? Give feedback.


I rewrote #1189, and it's more reasonable for me.
https://stackblitz.com/edit/valtio-stress-test-qzyuj3k5?file=package.json,src%2Fmain.ts
It's improved, and it's the best at the moment.
In the future, we may introduce
batch()in v3, which might help this case.