BMi*_*ner 104 javascript arrays performance v8 object
与JavaScript中的数组和对象(尤其是Google V8)相关的性能对于文档来说非常有趣.我在互联网上找不到关于这个主题的综合文章.
我知道一些对象使用类作为它的底层数据结构.如果有很多属性,它有时被视为哈希表?
我也理解,数组有时被视为C++数组(即快速随机索引,慢速删除和调整大小).而且,其他时候,它们更像对象(快速索引,快速插入/删除,更多内存).并且,有时它们可能存储为链接列表(即慢速随机索引,在开头/结尾快速删除/插入)
JavaScript中的数组/对象检索和操作的精确性能是什么?(专门针对Google V8)
更具体地说,它对性能的影响如下:
任何文章或链接的更多细节也将不胜感激.:)
编辑:我真的很想知道JavaScript数组和对象是如何工作的.此外,在什么情况下 V8引擎"知道""转换"到另一个数据结构?
例如,假设我用...创建一个数组
var arr = [];
arr[10000000] = 20;
arr.push(21);
Run Code Online (Sandbox Code Playgroud)
这里到底发生了什么?
或者......这个怎么样...... ???
var arr = [];
//Add lots of items
for(var i = 0; i < 1000000; i++)
arr[i] = Math.random();
//Now I use it like a queue...
for(var i = 0; i < arr.length; i++)
{
var item = arr[i].shift();
//Do something with item...
}
Run Code Online (Sandbox Code Playgroud)
对于传统阵列,性能会很糟糕; 然而,如果使用了LinkedList ......那就不那么糟了.
Pic*_*tor 275
(我已经保存了测试用例的副本,并且一旦JSPref被修复/找到了后继者,它将更新答案)
嗯...对于答案来说可能有点过分......但我创建了一个测试套件,正是为了探索这些问题(以及更多)(存档副本).
从这个意义上讲,您可以在这个50多个测试用例测试器中看到性能问题(这需要很长时间).
另外正如其名称所示,它探讨了使用DOM结构的本机链表性质的用法.
摘要如下
Array.shift()是快速〜比阵列弹出快约6倍,但比对象属性删除快约100倍.Array.push( data );是,比Array[nextIndex] = data几乎20(动态阵列)到10(固定阵列)时间快.Array.unshift(data) 比预期慢,并且比新属性添加慢约5倍.array[index] = null比delete array[index]在数组中删除它(未定义)快〜约4x ++更快.obj[attr] = null比仅删除属性大约慢2倍delete obj[attr]Array.splice(index,0,data)很慢,非常慢.Array.splice(index,1,data)已经过优化(无长度变化),比拼接速度快100倍Array.splice(index,0,data)dll.splice(index,1)删除(它打破了测试系统).注意:这些指标仅适用于v8不"完全优化"的大型数组/对象.对于阵列/对象大小小于任意大小(24?),可能存在非常孤立的优化性能情况.可以在多个Google IO视频中广泛查看更多详细信息.
注意2:这些精彩的性能结果不会在浏览器之间共享,尤其是
*cough*IE.此外测试是巨大的,因此我还没有完全分析和评估结果:请在=)中编辑它
更新的注释(2012年12月): Google代表在youtubes上有视频,描述了Chrome本身的内部工作原理(比如从链接列表数组切换到固定数组等),以及如何优化它们.有关更多信息,请参阅GDC 2012:从控制台到Chrome.
更新的注释(2013年2月): Thx @badunk,用于在确切的位置提供视频链接
更新的注释(2016年6月): Thx @Benedikt,关于固定/动态阵列中的阵列推送性能差异.
小智 5
在保持在JavaScript领域内的基本级别上,对象的属性是更复杂的实体.您可以使用setter/getter创建属性,具有不同的可枚举性,可写性和可配置性.无法以这种方式自定义数组中的项:它是存在还是不存在.在底层引擎级别,这允许在组织表示结构的存储器方面进行更多优化.
在从对象(字典)中识别数组方面,JS引擎总是在两者之间做出明确的界限.这就是为什么有很多关于尝试制作半假的类似于对象的方法的文章,这些对象的行为类似于一个但允许其他功能.这种分离甚至存在的原因是因为JS引擎本身以不同的方式存储这两者.
属性可以存储在数组对象上,但这只是演示了JavaScript如何坚持将所有内容都设为对象.数组中的索引值的存储方式与您决定在表示基础数组数据的数组对象上设置的任何属性的存储方式不同.
每当你使用一个合法的数组对象并使用一种操作该数组的标准方法时,你就会遇到底层的数组数据.特别是在V8中,这些与C++数组基本相同,因此这些规则将适用.如果由于某种原因你正在使用一个引擎无法自信地确定阵列的阵列,那么你就会更加不稳定.随着最新版本的V8,有更多的工作空间.例如,可以创建一个以Array.prototype作为其原型的类,并且仍然可以有效地访问各种本机数组操作方法.但这是最近的变化.
最近更改数组操作的特定链接可能会派上用场:
作为额外的一点,这里是直接来自V8源码的Array Pop和Array Push,两者都是用JS本身实现的:
function ArrayPop() {
if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
throw MakeTypeError("called_on_null_or_undefined",
["Array.prototype.pop"]);
}
var n = TO_UINT32(this.length);
if (n == 0) {
this.length = n;
return;
}
n--;
var value = this[n];
this.length = n;
delete this[n];
return value;
}
function ArrayPush() {
if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
throw MakeTypeError("called_on_null_or_undefined",
["Array.prototype.push"]);
}
var n = TO_UINT32(this.length);
var m = %_ArgumentsLength();
for (var i = 0; i < m; i++) {
this[i+n] = %_Arguments(i);
}
this.length = n + m;
return this.length;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
36646 次 |
| 最近记录: |