Three.js:如何正确释放场景内存

6

我在响应式应用程序中使用three.js时遇到了许多消除内存泄漏问题的困难。调查问题后,我发现即使不进行渲染,我也无法正确地释放场景。 让我给你看看:

https://plnkr.co/edit/Z0sXOnXYc2XOV4t9tETv

在上面的例子中,最初实例化了3个对象(你可以看到没有渲染,只是实例化对象):
  • 场景(scene)
  • 相机(camera)
  • 渲染器(renderer)
使用Chrome开发者工具,在页面加载后立即拍摄一张内存快照。

enter image description here

现在让我们点击“添加1000个网格”按钮,你可以猜到它会简单地创建1000个网格(BoxGeometry + MeshBasicMaterial)并将它们添加到场景对象中。让我们再次拍摄一张内存快照,并与上一个快照进行比较(增量):

enter image description here

正如您所看到的,我们从25.2 Mb增加到了36.2 Mb,并且有超过1000个网格对象被添加到内存中。

现在点击“DISPOSE”按钮,我们将触发以下dispose函数:

 const dispose = (e) => {           

    // dispose geometries and materials in scene
    sceneTraverse(scene, o => {

        if (o.geometry) {
            o.geometry.dispose()
            console.log("dispose geometry ", o.geometry)                        
        }

        if (o.material) {
            if (o.material.length) {
                for (let i = 0; i < o.material.length; ++i) {
                    o.material[i].dispose()
                    console.log("dispose material ", o.material[i])                                
                }
            }
            else {
                o.material.dispose()
                console.log("dispose material ", o.material)                            
            }
        }
    })          

    scene = null
    camera = null
    renderer && renderer.renderLists.dispose()
    renderer = null

    addBtn.removeEventListener("click", addMeshes)
    disposeBtn.removeEventListener("click", dispose)

    console.log("Dispose!")
}

在这个函数中,我们遍历场景并处理每一个几何体和材质。然后,我们将场景、相机和渲染器的引用设置为null,并最终移除监听器以避免内存泄漏。让我们点击DISPOSE按钮并再次进行内存快照。我期望垃圾收集器会完全从内存中删除与1000个Meshes(Mesh、Matrix4、Vector3、BoxGeometry等)相关的所有数据,但如果我们再次进行内存快照,我们会发现有些不同。

enter image description here

看起来已经删除了1000个网格对象,但内存使用量与先前的快照几乎相同(34.6 vs 36.2 Mb)。Vector3,Matrix4,Quaternion和Euler对象有一些下降,但大多数对象仍保留在内存中,并且不会被垃圾收集器回收。实际上,如果我们将第3个快照与第1个快照进行比较,我们会发现确切地如下:

enter image description here

请问有人能解释一下发生了什么,以及如何在three.js中正确处理事情吗?
Three.js版本:102 Google Chrome版本:72.0.3626.121(64位)

请查看 https://dev59.com/KFwX5IYBdhLWcg3w-Tlv#33199591 - gaitat
谢谢,尝试了但没有任何改变。 - revy
我有完全相同的问题。在材质和几何体上调用dispose并不能完全清除内存。从场景中移除网格也不能完全清除。而且删除控制台日志也不能完全清除。哈哈。 - Joe C
更多信息请参见 https://github.com/mrdoob/three.js/pull/12464。 - Joe C
1个回答

10

问题实际上是由 console.log 语句引起的,这些语句阻止了在 Chrome 控制台中打印的对象进行垃圾回收。删除 console.log 语句解决了这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接