首页 > 解决方案 > JavaScript 中的内存管理技术

问题描述

TL;DR -- 从内存管理的角度来看,这两种返回值的方法有什么区别?它们在游戏循环中进行管理,每秒修改数千次。

return { x: x1 + x2, y: y1 + y2, z: z1 + z2 }

// VS

predeclared.x = x1 + x2;
predeclared.y = y1 + x2;
predeclared.z = z1 + x2;

return predeclared;

感谢您的任何见解!

一些上下文......在某些情况下,在 webGL / three.js 程序中,预先声明一个虚拟引用是有益的,该引用将用于在每一帧临时保存一个对象,而不是创建一个新对象来帮助垃圾收集。我很确定这是一种常见的做法,但以防万一它看起来像这样:

let mesh;

while( true ) {
  mesh = getNewMeshFrame( time );
  renderStuff( mesh );
}

我不确定在以下情况下使用的正确技术。

// With just ONE predeclared object and an object literal in the return statement
function box() {
  let box = { x: 0, y: 0 };

  this.transform = function( addX, addY ) {
    return { x: box.x + addX, y: box.y + addY }; 
  }
}

// OR, with TWO predeclared objects
function box() {
  let box = { x: 0, y: 0 };
  let transformed = { x: 0, y: 0 };

  this.transform = function( addX, addY ) {  
    transformed.x = box.x + addX;
    transformed.y = box.y + addY;    
    return transformed; 
  }
}

我希望很明显,盒子对象是静态的并且不能改变(它是一个更复杂的对象 IRL),所以我需要将它与它的变换分开。谢谢!

标签: javascriptmemory-managementgarbage-collection

解决方案


每次transform()调用返回对象字面量的版本都会分配一个新对象。这些将随着时间的推移在内存中累积,最终需要进行垃圾收集以删除不再使用的那些。

带有预声明变量的版本每次调用时都会返回对同一对象的引用。所以应该有更少的内存积累,更少的垃圾收集需求。但是,这意味着如果您将多个调用分配给不同的变量,它们都是对同一个对象的引用,该对象正在被修改。

b = new box();
t1 = b.transform(1, 2);
t2 = b.transform(3, 4);

与第一个版本,t1并且t2是不同的对象:

t1 = {x: 1, y: 2}
t2 = {x: 3, y: 4}

在第二个版本中,它们是同一个对象:

t1 = t2 = {x: 3, y: 4}

如果这对程序的其余部分没有问题,那么如果您transform()在同一个盒子上多次调用,第二个版本应该会显着提高内存效率。

但是,不同的盒子之间没有共享。

b1 = new box();
b2 = new box();

b1.transform()在这两个版本中,和之间没有冲突b2.transform()


推荐阅读