JavaScript类型的内存分配

时间:2013-09-23 23:24:07

标签: javascript performance memory

我正在尝试优化我正在处理的移动应用程序的地狱,我想知道什么占用最小的内存占用(我意识到这可能因浏览器而异):

  • 对象指针
  • 布尔文字
  • 数字文字
  • 字符串文字

理论上应该占用最少的内存空间?

2 个答案:

答案 0 :(得分:16)

在V8上:

Boolean,number,string,null和void 0 literals将常量的4/8字节的内存用于指针或嵌入指针的立即整数值。但是根本没有堆分配,因为字符串文字将被内化。异常可以是大整数或双精度,其中框指针为4/8字节,框为12-16字节。在优化的代码中,本地双精度数可以在寄存器或堆栈中保持未装箱,或者总是只包含双精度数组的数组会将它们保存为未装箱的。

考虑the meat of the generated code

function weird(d) {
    var a = "foo";
    var b = "bar";
    var c = "quz";

    if( d ) {
        sideEffects(a, b, c);
    }
}

正如您所看到的,指向字符串的指针是硬编码的,不会发生分配。

对象标识至少需要12/24字节用于普通对象,16/32字节用于数组,32/72用于函数(如果需要分配上下文对象,则为+ ~30 / 60字节)。如果你运行前沿v8并且标识没有转义为无法内联的函数,那么你只能在没有堆分配的情况下离开。

例如:

function arr() {
    return [1,2,3]
}

值1,2,3的后备数组将由函数返回的所有数组共享为写时复制数组,但仍需要为每个数组分配唯一的标识对象。看看generated code is有多复杂。因此,即使使用此优化,如果您不需要数组的唯一标识,只需从上部作用域返回一个数组将避免每次调用该函数时为该标识分配:

var a = [1,2,3];
function arr() {
    return a;
}

Much simpler.

如果你有js的内存问题而没有做任何看似疯狂的事情,你肯定会动态创建函数。将所有功能提升到不需要重新创建的级别。正如您从上面所看到的,仅仅考虑到大多数代码可以通过利用this来摆脱静态函数,函数的身份已经非常胖了。

因此,如果您想从中获取任何内容,请避免非IIFE关闭,如果您的目标是性能。任何表明它们不是问题的基准都是破碎的基准。

你可能有直觉,当你拥有8GB时,额外的内存使用会有什么影响。好吧,它在C中没关系。但是在Javascript中,内存不只是坐在那里,它被垃圾收集器跟踪。存在的内存和对象越多,性能就越差。

考虑运行类似:

var l = 1024 * 1024 * 2
var a = new Array(l);

for( var i = 0, len = a.length; i < len; ++i ) {
    a[i] = function(){};
}

--trace_gc --trace_gc_verbose --print_cumulative_gc_statJust look how much work一无所获。

与静态功能比较:

var l = 1024 * 1024 * 2
var a = new Array(l);
var fn = function(){};

for( var i = 0, len = a.length; i < len; ++i ) {
    a[i] = fn;
}

答案 1 :(得分:0)

“Literal”表示代码(即使不在字符串序列化中),这是一种更复杂的类型,因此会比花费更多的空间。

理论上,布尔值可以占用最少的空间,因为它们适合单个位。虽然任何发动机都不会对此进行优化,但它不太可能。如果要强制执行此操作,可以手动执行此操作并使用类型化数组进行操作。

但是,性能是实用的东西,你只能测试,测试和测试它。如您所知,没有明确的跨浏览器跨版本答案。