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

时间:2015-06-05 15:27:26

标签: 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);
};

Heap allocations by functions

以上屏幕截图是以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);
}

可能的答案:

  

任何时候将浮点数分配给某个属性   对象或数组的元素,必须先装箱(分配在   堆)。如果你的程序执行了很多浮点数学,   拳击可能是昂贵的。使用对象时无法避免拳击   属性,但在数组上操作时,可以使用类型化数组   避免拳击。

来自Writing efficient JavaScript

0 个答案:

没有答案