Moh*_*sen 144 javascript performance
我运行此代码并得到以下结果.我很想知道为什么[]
更快?
console.time('using[]')
for(var i=0; i<200000; i++){var arr = []};
console.timeEnd('using[]')
console.time('using new')
for(var i=0; i<200000; i++){var arr = new Array};
console.timeEnd('using new')
Run Code Online (Sandbox Code Playgroud)
[]
:299msnew
:363ms感谢Raynos,这里是此代码的基准,以及一些更可行的方法来定义变量.
小智 194
进一步扩展以前的答案......
从一般编译器的角度出发,忽略特定于VM的优化:
首先,我们通过词法分析阶段,我们将代码标记化.
举例来说,可以生产以下令牌:
[]: ARRAY_INIT
[1]: ARRAY_INIT (NUMBER)
[1, foo]: ARRAY_INIT (NUMBER, IDENTIFIER)
new Array: NEW, IDENTIFIER
new Array(): NEW, IDENTIFIER, CALL
new Array(5): NEW, IDENTIFIER, CALL (NUMBER)
new Array(5,4): NEW, IDENTIFIER, CALL (NUMBER, NUMBER)
new Array(5, foo): NEW, IDENTIFIER, CALL (NUMBER, IDENTIFIER)
Run Code Online (Sandbox Code Playgroud)
希望这应该为您提供足够的可视化,以便您了解需要多少(或更少)处理.
基于上述标记,我们知道ARRAY_INIT将始终生成一个数组.因此,我们只需创建一个数组并填充它.至于歧义,词法分析阶段已经将ARRAY_INIT与对象属性访问器(例如obj[foo]
)或字符串/正则表达式文字中的括号(例如"foo [] bar"或/ [] /)区分开来
这是微不足道的,但我们也有更多的令牌new Array
.此外,还不完全清楚我们只是想创建一个数组.我们看到"新"令牌,但"新"令牌是什么?然后我们看到IDENTIFIER标记,表示我们想要一个新的"数组",但JavaScript VM通常不区分IDENTIFIER标记和"本机全局对象"的标记.因此...
每次遇到IDENTIFIER令牌时,我们都必须查找范围链.Javascript VM包含每个执行上下文的"激活对象",其中可能包含"arguments"对象,本地定义的变量等.如果我们无法在Activation对象中找到它,我们将开始查找范围链,直到我们到达全局范围.如果没有找到,我们扔了一个ReferenceError
.
一旦我们找到变量声明,我们就会调用构造函数. new Array
是一个隐式函数调用,经验法则是函数调用在执行期间较慢(因此静态C/C++编译器允许"函数内联" - SpiderMonkey等JS JIT引擎必须在运行中执行)
该Array
构造函数重载.Array构造函数实现为本机代码,因此它提供了一些性能增强,但仍需要检查参数长度并相应地执行操作.此外,如果只提供了一个参数,我们需要进一步检查参数的类型.new Array("foo")产生["foo"],其中新的Array(1)产生[undefined]
所以为了简化它:使用数组文字,VM知道我们想要一个数组; 因此new Array
,VM需要使用额外的CPU周期来确定new Array
实际操作的内容.
归档时间: |
|
查看次数: |
52035 次 |
最近记录: |