Проблема со сборкой мусора ThreeJS

Я создал приложение ThreeJS, используя средство визуализации холста (из-за требований проекта), с которым я столкнулся с проблемой памяти/сборки мусора.

Часть логики приложения создает множество сеток для достижения анимации на сегментах плоского двумерного пончика/кольца. При каждом проходе анимации мы удаляем все предыдущие сетки и создаем новые.

Когда объекты удаляются со сцены, они не удаляются из памяти, а перемещаются в массив с именем __objectsRemoved. Это сохраняется на неопределенный срок - я полагаю, что есть какая-то сборка мусора, которая в конечном итоге все очищает, но я не знаю, как это вызвать. Использование памяти приложением постоянно растет, пока оно не остановит браузер в течение 30-40 секунд.

Мы не смогли решить эту проблему и отчаянно ищем совета. Этот проект должен быть запущен очень скоро, поэтому мы будем очень признательны за любые немедленные рекомендации/советы.

Вот скрипка, которая иллюстрирует проблему. http://jsfiddle.net/729sv/

var camera, scene, renderer;
var base = 0;

init();
animate();

function init() {
    renderer = new THREE.CanvasRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    scene = new THREE.Scene();

    camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1000);
    camera.position.z = 100;

    document.addEventListener('mousedown', update, false);

    update();
}

function update() {

    if (base) scene.remove(base);

    base = new THREE.Object3D();
    scene.add(base);

    for (var j = 0; j < 10; ++j) {

        var geometry = new THREE.IcosahedronGeometry(50, 3);
        var material = new THREE.MeshNormalMaterial()
        var mesh = new THREE.Mesh(geometry, material);
        base.add(mesh);
    }
}

function animate() {
    requestAnimationFrame(animate);
    console.log(scene.__objectsRemoved.length);
    renderer.render(scene, camera);
}

Мы используем ThreeJS R62.

Спасибо!


person Funkmyer    schedule 21.12.2013    source источник
comment
Почему вы держите объекты вокруг на неопределенный срок? Я считаю, что ваша проблема может быть связана с тем, что вы навсегда храните «удаленные» объекты. Поскольку вы постоянно записываете в массив, он никогда ничего из него не удалит. Либо перезапишите свои значения, либо просто отбросьте вещи.   -  person Justin Wood    schedule 21.12.2013
comment
Не создавайте/удаляйте объекты в каждом проходе анимации. Вместо этого создайте пул объектов и используйте их повторно. См., например, threejs.org/examples/webgl_particles_shapes.html.   -  person WestLangley    schedule 21.12.2013
comment
Привет, ребята, спасибо за ответы. Джастин, на самом деле я удаляю объекты, а библиотека, похоже, хранит удаленные элементы в массиве. Это проблема, которую я пытаюсь обойти. @WestLangley, я создаю индивидуальную геометрию формы для каждой анимации сегментов пончика по мере их роста или сжатия. Я не уверен в более эффективном методе для достижения этой цели, но приветствую любые предложения.   -  person Funkmyer    schedule 21.12.2013
comment
Если бы был способ создать эти сегменты один раз, а затем просто анимировать вершины для расширения контракта, это было бы намного эффективнее, чем текущий метод. Я могу опубликовать этот конкретный код здесь или в другом сообщении SO, если вы хотите его увидеть.   -  person Funkmyer    schedule 21.12.2013
comment
Я сделаю все возможное, чтобы ответить на конкретные вопросы о three.js.   -  person WestLangley    schedule 21.12.2013
comment
@WestLangley, спасибо. Я разместил этот вопрос в его собственной теме. stackoverflow.com/questions/20722655/   -  person Funkmyer    schedule 21.12.2013


Ответы (1)


Это ошибка в библиотеке. Извини за это :(

Не могу поверить, что мы до сих пор этого не сделали... __objectsAdded и __objectsRemoved были добавлены для WebGLRenderer из соображений производительности. Однако мы забыли о побочных эффектах, которые это создает на других средствах визуализации (я вижу, вы используете CanvasRenderer...)

В качестве обходного пути... Вы можете попробовать переопределить эти массивы:

scene = new THREE.Scene();

if ( renderer instanceof THREE.CanvasRenderer ) {

    scene.__lights = { length: 0, push: function(){}, indexOf: function (){ return -1 }, splice: function(){} }
    scene.__objectsAdded = { length: 0, push: function(){}, indexOf: function (){ return -1 }, splice: function(){} }
    scene.__objectsRemoved = { length: 0, push: function(){}, indexOf: function (){ return -1 }, splice: function(){} }

}
person mrdoob    schedule 22.12.2013
comment
Спасибо! Я попробую это и посмотрю, разберется ли это. - person Funkmyer; 22.12.2013
comment
Это сработало, еще раз спасибо за помощь в этом и за всю вашу работу над фантастической библиотекой. - person Funkmyer; 22.12.2013
comment
Исправлено ли это в three.js R66? Обходной путь создал для меня некоторые проблемы. - person Sam Stainsby; 28.04.2014
comment
Пока нет... Какие проблемы это создало? - person mrdoob; 29.04.2014