Memory leak when switching models in <model-viewer> compared to three.js implementation
Hi, thank you for maintaining this great project.
I'm encountering a significant memory leak issue when using model-viewer to switch between different 3D models in a web app. I built a side-by-side comparison with a similar app implemented using three.js, and found that model-viewer does not release memory properly when switching models.
Test Cases: I prepared two demo apps for comparison:
- three.js version: https://modelview-dev2.netlify.app/share/threejs-viewer/
- model-viewer version: https://modelview-dev2.netlify.app/share/model-viewer/
Both apps work the same: Select a model from a list (e.g., dishwasher or TV), Load it in a viewer screen, Return to the list and select another model.
Observed Behavior: The three.js version shows expected memory usage changes depending on model size (~100MB for dishwasher, ~30MB for TV), with memory properly released when switching.
The model-viewer version shows continuous memory accumulation after each model switch, even when returning to previously loaded models.
Heap Snapshot Results: I have captured heap snapshots using Chrome DevTools at various stages (initial load, after selecting large/small models, switching back and forth).
Heap snapshot of the three.js version
Heap snapshot of the model-viewer version
A comparison chart showing memory growth over time
Attempts to Resolve: I tried setting modelCacheSize to 0 or 1, but memory usage actually worsened compared to the default value (5).
I also used Object.getOwnPropertySymbols() to access the internal scene and manually dispose() geometries and materials, but this didn’t release the memory either.
I understand that model-viewer manages the rendering process internally, but it seems the internal scene or renderer is not fully releasing resources when switching models.
Reproducible Example: To make it easier to inspect or modify the source code, I created editable Plnkr projects:
- Three.js version: https://plnkr.co/edit/L7S2KqS9pEPinZGA
- model-viewer version: https://plnkr.co/edit/mRa1fK7TC9CtTg9m
(Note: Since the Plnkr environment wraps the app with additional UI, heap snapshots taken there may appear significantly larger than in the standalone app.)
Impact: This issue causes out-of-memory crashes on low-memory devices (e.g., webOS TVs). Right now, I’m only switching between two models, so the heap snapshot increase is somewhat limited. But in real use cases, when loading 3 or 4 different models, the memory keeps growing with each model. On actual webOS TV devices, this eventually causes the app to crash due to memory exhaustion.
I'd really appreciate any guidance on how to properly clean up resources when switching models, or whether this is a known issue being addressed.
Thanks again!
Have you tried removing the
Something like this: https://codepen.io/samanehk/pen/qEdwKWo
<script>
// List of models to switch between
const models = [
'https://modelviewer.dev/shared-assets/models/soldier.glb',
'https://modelviewer.dev/shared-assets/models/NeilArmstrong.glb'
];
let currentModelIndex = 0;
function createModelViewer(modelUrl) {
const modelViewer = document.createElement('model-viewer');
modelViewer.setAttribute('src', modelUrl);
modelViewer.setAttribute('alt', '3D model');
modelViewer.setAttribute('camera-controls', '');
modelViewer.setAttribute('auto-rotate', '');
modelViewer.style.width = '400px';
modelViewer.style.height = '300px';
return modelViewer;
}
function loadModel(index) {
const container = document.getElementById('viewer-container');
// Remove old <model-viewer> if it exists
container.innerHTML = '';
// Create and append new <model-viewer>
const newViewer = createModelViewer(models[index]);
container.appendChild(newViewer);
}
// Initial load
loadModel(currentModelIndex);
document.getElementById('switch-model').addEventListener('click', () => {
// Switch to the next model
currentModelIndex = (currentModelIndex + 1) % models.length;
loadModel(currentModelIndex);
});
</script>
@samaneh-kazemi
Thank you for the quick reply.
As I recall, I had tried a similar approach before, though not exactly the same. This time, I tested your code as-is using our assets, but unfortunately the issue still remains.
You can see it here: https://modelview-dev2.netlify.app/share/multi-model/
Below is a screenshot of the heap snapshots.
I have also encountered this problem. On Android phones, it is easy to overflow memory after switching several models, but not on iOS phones.