You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Memory Leak: OtaVersion instances wrapped with ref() are never garbage collected when overwritten
Bug Description
Summary
When using Valtio's ref() function to wrap objects, repeatedly calling onVersionInfo() to create new OtaVersion instances causes a severe memory leak. Old instances are never garbage collected, even after being overwritten.
Steps to Reproduce
In App.tsx, the useEffect hook calls initVersionInfo() 10,000 times in a loop
Each call creates a new OtaVersion instance wrapped with ref()
The new instance overwrites deviceStore.otaVersion, but the old instance is not released
Click the "test" button on the page to call unstable_getInternalStates()
Observe that Valtio's internal state holds references to all 10,000 OtaVersion objects
Problematic Code
**App.tsx(lines13-17):**useEffect(()=>{for(leti=0;i<10000;i++){initVersionInfo();}},[]);**Device.ts(lines31-43):**onVersionInfo(): void{// Simulate OTA module dataconst otaModules =['module-a','module-b','module-c'];// Use ref() to wrap so OtaVersion instance won't be proxied by Valtiothis.otaVersion=ref(newOtaVersion({state: otaModules[0],sn: this.id,modelName: this.originModelName,}));this.status='online';}
Root Cause
The ref() function marks objects as non-proxyable, and Valtio maintains internal references to these objects. When this.otaVersion is overwritten with a new value, the old ref()-wrapped object remains held by Valtio's internal state, preventing garbage collection.
Expected Behavior
When this.otaVersion is overwritten with a new instance, the old OtaVersion instance should be eligible for garbage collection.
Actual Behavior
All OtaVersion instances wrapped with ref() are retained in Valtio's internal state and are never released, causing a memory leak.
Impact
In production environments, frequently calling onVersionInfo() to update version information causes continuous memory growth
Long-running applications may crash due to memory exhaustion
Each overwritten ref() object remains in memory indefinitely
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
Bug Description
Title
Memory Leak: OtaVersion instances wrapped with ref() are never garbage collected when overwritten
Bug Description
Summary
When using Valtio's
ref()function to wrap objects, repeatedly callingonVersionInfo()to create newOtaVersioninstances causes a severe memory leak. Old instances are never garbage collected, even after being overwritten.Steps to Reproduce
App.tsx, theuseEffecthook callsinitVersionInfo()10,000 times in a loopOtaVersioninstance wrapped withref()deviceStore.otaVersion, but the old instance is not releasedunstable_getInternalStates()OtaVersionobjectsProblematic Code
Root Cause
The
ref()function marks objects as non-proxyable, and Valtio maintains internal references to these objects. Whenthis.otaVersionis overwritten with a new value, the oldref()-wrapped object remains held by Valtio's internal state, preventing garbage collection.Expected Behavior
When
this.otaVersionis overwritten with a new instance, the oldOtaVersioninstance should be eligible for garbage collection.Actual Behavior
All
OtaVersioninstances wrapped withref()are retained in Valtio's internal state and are never released, causing a memory leak.Impact
onVersionInfo()to update version information causes continuous memory growthref()object remains in memory indefinitelyEnvironment
Reproduction Link
https://valtio-demo-ten.vercel.app/ https://github.com/childrentime/valtio-demo
Beta Was this translation helpful? Give feedback.
All reactions