Оптимальная практика удаления трехмерной геометрии?

Если у меня есть что-то вроде следующего:

myObj = new THREE.Object3d;
scene.add(myObj); 
doIt();

function doIt(){
 var geometry = new THREE.SphereGeometry( 1, 8, 8 );
 var mesh = new THREE.Mesh( geometry, meshMaterial );
 myObj.add(mesh);
}

насколько я понимаю, geometry переменных и mesh становятся неназначенными, как только функция завершается. Но объект scene все еще содержит myObj, который все еще содержит сетку, которая по-прежнему содержит геометрию. Итак, теперь геометрия живет внутри myObj внутри scene. Докажу ли я до сих пор?

Но если я тогда сделаю

scene.remove(myObj);

а также

myObj = new Object();

Тогда я подумал, что больше нет сетки, нет геометрии. У меня больше нет какой-либо существующей переменной или объекта, который содержит или ссылается на эти вещи. Но они все еще существуют где-то, занимая память?

Есть функция dispose dispose() в three.js, но я не понимаю, где в моей последовательности кода она должна быть нормально применена или именно по этой причине?

Я работаю над проектом, который необходимо создать, а затем удалить много объектов, поэтому я боюсь, если я не сделаю это правильно, будут проблемы с производительностью.

Любая мудрость очень ценится.

1 ответ

В javascript объекты существуют в памяти до тех пор, пока они не будут очищены сборщиком мусора. Назначив новый объект переменной, вы просто создаете новую переменную с тем же именем. Старые данные все еще существуют в памяти до тех пор, пока сборщик мусора не запустит и не удалит старые данные из памяти.

Поскольку память JavaScript только очищается сборщиком мусора, и вы не можете вручную запускать сборку мусора (и вам не нужно), вы должны использовать пул объектов вместо создания тонны одноразовых объектов.

Примечание. Это не означает, что вы всегда должны использовать пул объектов, но вместо этого вы должны использовать пул объектов, если вы обнаружите, что создаете и разыменовываете большое количество объектов за короткий промежуток времени. Помните, преждевременно не оптимизируйте.

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

источник

Вы можете найти различные шаблоны для пула объектов онлайн, но вот пример: https://gist.github.com/louisstow/5609992

Обратите внимание: нет причин держать большой пул лишних объектов в памяти, если вы больше не создаете большое количество объектов. Вы должны уменьшить размер пула, освободить неиспользуемые объекты и позволить GC собирать их. Вы всегда можете увеличить размер, если вам нужно. Просто не переключайтесь между сокращением и увеличением размера пула слишком быстро, иначе вы просто победите точку пула объектов.

var objectPool = [];
var marker = 0;
var poolSize = 0;

//any old JavaScript object
function commonObject () { }

commonObject.create = function () {
 if (marker >= poolSize) {
 commonObject.expandPool(poolSize * 2);
 }

 var obj = objectPool[marker++];
 obj.index = marker - 1;
 obj.constructor.apply(obj, arguments);
 return obj;
}

//push new objects onto the pool
commonObject.expandPool = function (newSize) {
 for (var i = 0; i < newSize - poolSize; ++i) {
 objectPool.push(new commonObject());
 }

 poolSize = newSize;
}

//swap it with the last available object
commonObject.prototype.destroy = function () {
 marker--;
 var end = objectPool[marker];
 var endIndex = end.index;

 objectPool[marker] = this;
 objectPool[this.index] = end;

 end.index = this.index;
 this.index = endIndex;
}

//make this as big as you think you need
commonObject.expandPool(1000);

licensed under cc by-sa 3.0 with attribution.