为什么JS中的简单数学会分配大量内存

Han*_*ody 5 javascript memory optimization node-webkit

为什么以下代码分配了大量内存?

Entity3D.prototype._updateEuler = function(elapsed) {
    this.velocity.x += this.force.x / this.mass * elapsed;
    this.velocity.y += this.force.y / this.mass * elapsed;
    this.velocity.z += this.force.z / this.mass * elapsed;

    var initialSpeed = this.speed = vector3.length(this.velocity);
    if (this.speed && this.deceleration)
        this.speed = Math.max(0, this.speed - this.deceleration*elapsed);
    if (this.speed > this.maxSpeed)
        this.speed = this.maxSpeed;
    if (this.speed !== initialSpeed) {
        this.velocity.x = this.velocity.x / initialSpeed * this.speed;
        this.velocity.y = this.velocity.y / initialSpeed * this.speed;
        this.velocity.z = this.velocity.z / initialSpeed * this.speed;
    }

    this.oldPosition.x = this.position.x;
    this.oldPosition.y = this.position.y;
    this.oldPosition.z = this.position.z;
    this.position.x += this.velocity.x * elapsed;
    this.position.y += this.velocity.y * elapsed;
    this.position.z += this.velocity.z * elapsed;

    if (this.speed > 0)
        vector3.normalize(this.velocity, this.heading);
};
Run Code Online (Sandbox Code Playgroud)

按功能分配堆

上面的截图是在以60 FPS运行游戏40秒后,每帧更新大约200个Entity3D对象,_updateEuler()在此期间被调用大约500 000次.

上面代码中的所有属性都是常规数字或由对象文字创建的简单对象:{'x': 0, 'y': 0, 'z': 0}它们是在创建对象时创建的,而不是每个帧.这意味着,上面的代码只是做了一些简单的数学运算并为属性赋值.

Entity3D是一个表示某些游戏对象(包括粒子)的简单类.我在启动时分配了大约200个这些对象,并通过重置其属性而不是分配全新实例来重用它们.

我的问题是:

  • 我是否正确读取了探查器,这个函数是否真的因某种原因分配了40 MB的RAM?

  • 如何减少此功能中的内存分配?

上面代码中使用的函数:

function normalize(vector, out) {
    var l = Math.sqrt(vector.x*vector.x + vector.y*vector.y + vector.z*vector.z);
    if (l > 0) {
        out.x = vector.x / l;
        out.y = vector.y / l;
        out.z = vector.z / l;
    } else
        out.x = out.y = out.z = 0;
}

function length(vector) {
    return Math.sqrt(vector.x*vector.x + vector.y*vector.y + vector.z*vector.z);
}
Run Code Online (Sandbox Code Playgroud)

可能的答案:

只要将浮点数分配给对象的属性或数组的元素,就必须先将其装箱(在堆上分配).如果你的程序执行大量的浮点数学计算,那么装箱可能会很昂贵.使用对象属性时无法避免装箱,但在阵列上操作时,可以使用类型化数组来避免装箱.

编写高效的JavaScript