Three.js:如何正确地将场景放置在内存中 [英] Three.js: how to correctly dispose a scene in memory

查看:45
本文介绍了Three.js:如何正确地将场景放置在内存中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在响应式应用程序中使用

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

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

现在点击"DISPOSE"按钮,我们将触发以下处置功能:

  const dispose =(e)=>{//在场景中放置几何体和材质sceneTraverse(scene,o => {如果(o.geometry){o.geometry.dispose()console.log("dispose geometry",o.geometry)}如果(o.material){如果(o.material.length){for(let i = 0; i< o.material.length; ++ i){o.material [i] .dispose()console.log("dispose material",o.material [i])}}别的 {o.material.dispose()console.log("dispose material",o.material)}}})场景=空相机=空渲染器renderer.renderLists.dispose()渲染器= nulladdBtn.removeEventListener("click",addMeshes)disposeBtn.removeEventListener("click",dispose)console.log(处置!")} 

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

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

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

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

解决方案

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

I am having many problems to get rid of memory leaks using three.js in a reactive application. Investigating the problem, I found that I am not even able to correctly dispose a scene (without rendering). Let me show you:

https://plnkr.co/edit/Z0sXOnXYc2XOV4t9tETv

In the above example, initially 3 THREE objects are instantiated (as you can see there is no rendering going on, just instantiating the objects):

  • scene
  • camera
  • renderer

Using the chrome devtools let’s take a memory snapshot just after loading the page:

Now let’s click on the "ADD 1000 MESHES" button, which as you can guess simply create 1000 meshes (BoxGeometry + MeshBasicMaterial) and add them to the scene object. Let’s take another memory snapshot and see the comparison (delta) with the previous snapshot:

As you can see we passed from 25.2 Mb to 36.2 Mb and there are +1000 Mesh objects added in memory.

Now clicking the "DISPOSE" button we’ll trigger the following dispose function:

 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!")
}

In this function we traverse the scene and dispose every geometry and material. Then we set to null the references to scene, camera and renderer and finally we remove the listeners to avoid memory leaks. Let’s click on DISPOSE button and take another memory snapshot. I expected that the garbage collector will completely remove from memory all the data related to the 1000 Meshes (Mesh, Matrix4, Vector3, BoxGeometry, etc…) but if we take another memory snapshot we’ll find something very different:

It seems that 1000 Mesh objects have been deleted, but the memory usage is almost the same as in the previous snapshot (34.6 vs 36.2 Mb). There are some drops in the Vector3, Matrix4, Quaternion and Euler objects, but most of the objects keep to be persisted in memory and are not collected from the garbage collector. Indeed, if we compare the snapshot 3 to the snapshot 1 we find exactly that:

Please could someone explain what’s going on and how correctly dispose things in three.js?

Three.js: 102 Google Chrome: 72.0.3626.121 (64-bit)

解决方案

Actually the problem were the console.log statements which prevent to garbage-collect the objects printed on the chrome console. Removing the console.log statements solved the problem.

这篇关于Three.js:如何正确地将场景放置在内存中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆