如果我有以下内容:
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();
然后我会认为没有更多的网格,没有更多的几何。我不再拥有包含或引用这些东西的任何现存变量或对象。但它们仍然存在于某处,占据记忆?
在three.js中有一个dispose()
函数,但我不明白我的代码序列应该在哪里正常应用,或者究竟是为什么?
我正在开发一个需要创建然后删除大量对象的项目,所以我担心如果我做得不对,就会出现性能问题。
任何智慧都非常赞赏。
答案 0 :(得分: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);