三.js:如何在内存中正确配置场景

rev*_*evy 3 javascript garbage-collection memory-leaks google-chrome-devtools three.js

在响应式应用程序中使用three.js来消除内存泄漏时,我遇到了很多问题。调查问题后,我发现我什至无法正确处理场景(没有渲染)。让我演示给你看:

https://plnkr.co/edit/Z0sXOnXYc2XOV4t9tETv

在上面的示例中,最初实例化了 3 三个对象(如您所见,没有进行渲染,只是实例化了对象):

  • 场景
  • 相机
  • 渲染器

使用 chrome devtools 让我们在加载页面后拍摄内存快照:

在此处输入图片说明

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

在此处输入图片说明

如您所见,我们从 25.2 Mb 传递到 36.2 Mb,并且内存中添加了 +1000 个 Mesh 对象。

现在点击“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!")
}
Run Code Online (Sandbox Code Playgroud)

在这个函数中,我们遍历场景并处理每个几何体和材质。然后我们将场景、相机和渲染器的引用设置为 null,最后我们移除监听器以避免内存泄漏。让我们点击 DISPOSE 按钮并拍摄另一个内存快照。我预计,垃圾收集器将完全从内存中删除所有与1000个网格(网格,Matrix4,的Vector3,BoxGeometry等)的数据,但如果我们采取另一种内存快照,我们会发现非常不同的东西:

在此处输入图片说明

似乎删除了 1000 个 Mesh 对象,但内存使用情况与之前的快照几乎相同(34.6 对 36.2 Mb)。Vector3、Matrix4、Quaternion 和 Euler 对象中有一些下降,但大多数对象都保留在内存中,不会从垃圾收集器中收集。事实上,如果我们将快照 3 与快照 1 进行比较,我们会发现:

在此处输入图片说明

请有人解释发生了什么以及如何正确处理three.js中的东西?

three.js所:102谷歌浏览器:72.0.3626.121(64位)

rev*_*evy 5

实际上,问题在于 console.log 语句会阻止对 chrome 控制台上打印的对象进行垃圾收集。删除 console.log 语句解决了这个问题。