7

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

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

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

4

2 回答 2

17

在 V8 上:

Boolean、number、string、null 和 void 0 字面量为指针或嵌入在指针中的立即整数值占用恒定的 4/8 字节内存。但是这些根本没有堆分配,因为字符串文字只会被内部化。例外可以是大整数或双精度数,它们用 4/8 字节的盒子指针和 12-16 字节的盒子装箱。在优化的代码中,本地双精度值可以在寄存器或堆栈中保持未装箱,或者始终包含独占双精度值的数组将它们未装箱存储。

考虑生成代码的主要内容:

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 的支持数组将作为写入时复制数组被函数返回的所有数组共享,但对于需要分配的每个数组仍然是唯一的标识对象。看看生成的代码有多复杂。因此,即使进行了这种优化,如果您不需要数组的唯一标识,只需从上层范围返回一个数组即可避免每次调用函数时分配标识:

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

简单得多。

如果你有 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_stat. 看看有多少工作是白做的。

与静态函数比较:

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;
}
于 2013-09-24T07:07:16.607 回答
0

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

从理论上讲,布尔值可以占用最少的空间,因为它们适合单个位。尽管任何引擎都不太可能对此进行优化。如果您想强制执行此操作,您可以手动执行此操作并使用类型化数组进行处理。

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

于 2013-09-23T23:47:22.940 回答