Three.js: как правильно расположить сцену в памяти - PullRequest
1 голос
/ 13 марта 2019

У меня много проблем, чтобы избавиться от утечек памяти, используя three.js в реактивном приложении.Исследуя проблему, я обнаружил, что даже не могу правильно расположить сцену (без рендеринга).Позвольте мне показать вам:

https://plnkr.co/edit/Z0sXOnXYc2XOV4t9tETv

В вышеприведенном примере изначально создаются 3 ТРИ объекта (как вы можете видеть, что рендеринг не происходит, просто создание экземпляров объектов):

  • сцена
  • камера
  • рендеринг

Используя chrome devtools, давайте сделаем снимок памяти сразу после загрузки страницы:

enter image description here

Теперь давайте нажмем кнопку «ДОБАВИТЬ 1000 МЕШЕЙ», которая, как вы можете догадаться, просто создаст 1000 сеток (BoxGeometry + MeshBasicMaterial) и добавит их в сцену.объект.Давайте возьмем другой снимок памяти и посмотрим сравнение (дельта) с предыдущим снимком:

enter image description here

Как вы можете видеть, мы прошли от 25,2 Мб до 36,2 Мби в память добавлено +1000 объектов Mesh.

Теперь, нажав кнопку «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!")
}

В этой функции мы проходим сцену ираспоряжаться каждой геометрией и материалом.Затем мы устанавливаем нулевые ссылки на сцену, камеру и средство визуализации и, наконец, удаляем слушателей, чтобы избежать утечек памяти.Давайте нажмем кнопку DISPOSE и сделаем еще один снимок памяти.Я ожидал, что сборщик мусора полностью удалит из памяти все данные, связанные с 1000 мешами (Mesh, Matrix4, Vector3, BoxGeometry и т. Д.), Но если мы сделаем еще один снимок памяти, мы найдем что-то совсем другое:

enter image description here

Кажется, что 1000 объектов Mesh были удалены, но использование памяти почти такое же, как в предыдущем снимке (34,6 против 36,2 Мб).В объектах Vector3, Matrix4, Quaternion и Euler есть некоторые отбрасывания, но большинство объектов сохраняются в памяти и не собираются из сборщика мусора.Действительно, если мы сравним снимок 3 со снимком 1, мы обнаружим, что:

enter image description here

Пожалуйста, кто-нибудь может объяснить, что происходит и как правильно распорядиться вещамив three.js?

Three.js: 102 Google Chrome: 72.0.3626.121 (64-разрядная версия)

1 Ответ

0 голосов
/ 15 марта 2019

На самом деле проблема заключалась в операторах console.log, которые препятствуют сборке мусора объектов, напечатанных на консоли Chrome. Удаление операторов console.log решило проблему.

...