Javascript函数对象有多大?
我只是想知道如何在一个函数对象的开销。 在一个OOP设计模型中,你可以产生许多对象,每个对象都有它们自己的私有函数,但是如果你有10000个以上的对象,我认为这些私有函数对象会造成很大的开销。 我想知道是否有这样的情况:将这些函数移动到工具类或外部管理器来保存这些函数对象占用的内存是足够有利的。
这是Chrome如何处理功能,其他引擎可能做不同的事情。
让我们看看这个代码:
var funcs = [];
for (var i = 0; i < 1000; i++) {
funcs.push(function f() {
return 1;
});
}
for (var i = 0; i < 1000; i++) {
funcs[0]();
}
http://jsfiddle.net/7LS6B/4/
现在,引擎创建1000个功能。
单个函数本身几乎不占用任何内存(本例中为36个字节),因为它只保存一个指向所谓的SharedFunctionInfo对象的指针,该对象基本上是对源代码中函数定义的引用*。 这被称为懒惰解析。
只有当您经常运行它时,JIT才会启动,并创建函数的编译版本,这需要更多的内存。 所以, funcs[0]
占用256个字节:
*)这不完全正确,它也包含范围信息,函数的名称和其他元数据,这就是为什么它在这种情况下具有592字节的大小。
首先,在对象构造函数原型中放置方法是很常见的,因此它们将在给定对象的所有实例中共享:
function MyObject() {
....
}
MyObject.prototype.do_this = function() {
...
}
MyObject.prototype.do_that = function() {
...
}
还要注意,“函数对象”是一个常量代码块或闭包; 在这两种情况下,大小与代码无关:
x = [];
for (var i=0; i<1000; i++) {
x.push(function(){ ... });
}
数组中每个元素的大小不会取决于代码大小,因为代码本身将在所有函数对象实例之间共享。 对于1000个实例,每个实例都需要一些内存,但与其他对象(如字符串或数组)所需的内存大致相同,并且与该函数内存在多少代码无关。
如果使用Javascript eval
创建函数,情况会有所不同:在这种情况下,我希望每个函数都需要相当多的代码大小,并且与代码大小成比例,除非在此级别还完成了超级智能缓存和共享。
函数对象确实占用了很多空间。 对象本身可能不占用太多空间,如下所示,但函数对象似乎占用更多。 为了测试这个,我使用Function("return 2;")
来创建一个匿名函数数组。
结果如同OP所暗示的那样。 这些确实占据了空间。
创建
创建的这些Function()
100,000个从0开始使用75.4 MB。我在更受控制的环境中运行此测试。 这个转换更加明显,它表示每个函数对象将要消耗754个字节。 这些都是空的。 较大的函数对象可能会超过1kb,这将会非常快速地变得重要。 在客户端上旋转75MB并非微不足道,导致用户界面的锁定时间接近4秒。
这是我用来创建函数对象的脚本:
fs = [];
for(var i = 0; i < 100000; i++ ){
fs.push(Function("return 2;"));
}
调用这些函数也会影响内存级别。 调用函数增加了34MB的内存使用量。
叫
这是我以前称之为的:
for( var i = 0; i < fs.length; i++ ){
for( var a = 0; a < 1000; a++ ){
fs[i]();
}
}
在编辑模式下使用jsfiddle很难获得准确的结果,我建议将其嵌入。
Embedded jsFiddle Demo
这些陈述是不正确的,我让他们让评论保留上下文。
函数对象根本不占用太多空间。 可用的操作系统和内存将最终决定如何管理这种内存。 这并不会影响你应该担心的规模。
当加载到我的电脑上时,一个相对空白的jsfiddle消耗了5.4MB的内存。 创建100,000个函数对象后,它跳到7.5MB。 这似乎是每个函数对象的不重要的内存量(每个函数对象包含21个字节:7.5M-5.4M / 100k)。
jsFiddle Demo