我注意到各种对象实例化方法之间存在显着的性能差异。此外,似乎对象的大小(即属性的#)有时很重要。
任何人都可以对以下jsperf的结果有所了解吗? http://jsperf.com/objects-w-more-less-8-properties/5
var thisobj = {a:1,b:2,c:3,d:4,e:5,f:6,g:7,h:8}
这似乎是制定新对象的禁食方式
var thisobj = {a:1,b:2,c:3,d:4,e:5,f:6,g:7,h:8,i:9}
这个速度要慢得多......唯一的区别就是第9个值
var thisobj = new objsm(1,2,3,4,5,6,7,8);
AND
var thisobj = new objlg(1,2,3,4,5,6,7,8,9);
彼此差别不大(大概和预期的差不多),但它们仍然与上面的“动态”定义的对象有很大不同。他们的对象在这里定义:
var objsm = function (a,b,c,d,e,f,g,h) {
this.a = a; this.b = b; this.c = c; this.d = d; this.e = e; this.f = f; this.g = g; this.h = h;}
var objlg = function (a,b,c,d,e,f,g,h,i) {
this.a = a; this.b = b; this.c = c; this.d = d; this.e = e; this.f = f; this.g = g; this.h = h; this.i = i; }
为什么“var thisobj = {a:1,b:2,c:3,d:4,e:5,f:6,g:7,h:8}
”如此优越?
答案 0 :(得分:1)
这样的性能差异通常不是由于语言 javascript,而是由于该语言的实现。
其他因素,例如堆占用率(以及由此产生的GC成本)也会影响性能。
由于存在多种实现 - 这些实现在不断发展 - 并且浏览器不具备吐出生成的程序集的习惯,因此没有一般性的答案。
例如在FF 45上,我在所有四种情况下的表现几乎相同:
据推测,JIT编译器非常智能,可以在这里执行死代码消除,因此我们基本上对空循环进行基准测试。换句话说,这个结果显示了编译器的优化程度,而不是对象分配的成本。
Making the objects escape进入全局范围会产生以下结果,这些结果与人们期望的结果相符:
请注意,一个足够先进的编译器™可能会通过观察它们都写入同一个变量而不会在迭代之间进行读取来消除循环中的最后一个分配。
所以未来的浏览器版本可能会打破"打破"这个基准再次。
Microbenchmarks是一项棘手的业务。
答案 1 :(得分:0)
我的猜测是,基于hashmap的表单是本地执行,而基于构造函数的表单执行需要解释的函数。我想这种解释努力会导致表演的差异。
那8个属性的门槛怎么样? HashMap需要预先调整大小超过其应包含的最大值(如果不是,访问时间将增加)。如果某些浏览器供应商选择了较低的值(例如8-10),则每次存储超过8个项目的尝试都会降低性能。
但是,您提到的jsperf中的主要相关性并没有超出测试范围,而是通过浏览器:每个浏览器在所有测试中显示非常相似的结果,这是非常合理的