Three.js:如何正确地将场景放置在内存中

时间:2019-03-12 22:26:08

标签: javascript memory-leaks three.js garbage-collection google-chrome-devtools

在响应式应用程序中使用three.js来消除内存泄漏时,我遇到了很多问题。在研究问题时,我发现我什至无法正确放置场景(不渲染)。 让我告诉你:

https://plnkr.co/edit/Z0sXOnXYc2XOV4t9tETv

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

  • 场景
  • 相机
  • 渲染器

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

enter image description here

现在,我们单击“添加1000个网格”按钮,您可以猜测只需创建1000个网格(BoxGeometry + MeshBasicMaterial)并将其添加到场景对象中即可。 让我们获取另一个内存快照,并查看与上一个快照的比较(增量):

enter image description here

如您所见,我们从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!")
}

在此功能中,我们遍历场景并处理所有几何图形和材质。然后,将对场景,相机和渲染器的引用设置为空,最后删除监听器以避免内存泄漏。 让我们单击DISPOSE按钮并拍摄另一个内存快照。我希望垃圾收集器将从内存中完全删除与1000个网格有关的所有数据(Mesh,Matrix4,Vector3,BoxGeometry等),但是如果我们拍摄另一个内存快照,将会发现非常不同的东西:

enter image description here

似乎已经删除了1000个Mesh对象,但是内存使用率几乎与以前的快照相同(34.6 vs 36.2 Mb)。 Vector3,Matrix4,Quaternion和Euler对象中存在一些掉落,但是大多数对象仍然保留在内存中,并且不会从垃圾回收器中收集。确实,如果将快照3与快照1进行比较,就会发现:

enter image description here

请有人解释发生了什么以及如何正确地将内容放置在three.js中吗?

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

1 个答案:

答案 0 :(得分:-1)

实际上,问题出在console.log语句上,该语句可防止垃圾回收chrome控制台上打印的对象。删除console.log语句即可解决问题。