V8 上的 JavaScript 测试

标签 javascript node.js

function add(x, y) {  
   return x + y;  
}  

console.time("time1");

for (var i = 0; i < 90000000; ++i) {
    add(1, 2);   
    add('a','b');
}

console.timeEnd("time1");

function addText(x, y) {   
   return x + y;  
} 

function addNumber(x, y) {   
   return x + y;  
}

console.time("time2");

for (var i = 0; i < 90000000; ++i) {
    addNumber(1, 2);   
    addText('a','b');
}

console.timeEnd("time2");

结果是: 时间 1:1481 毫秒, time2: 102ms,

我在 nodejs 上运行这个测试,但我不知道为什么第一个测试比第二个慢。

最佳答案

这是因为参数类型更改导致引擎盖下发生了去优化。要知道这一点,我们必须知道优化 V8 做了什么:

内联

这是一项重要的优化,对于性能提升至关重要。它用函数体代替函数调用以加速执行。如果一个函数的大小很小,它将被内联。这假设在函数调用中,参数是固定的。

去优化

V8 在某些假设下进行优化。如果错误,它必须撤消那些优化,以便它能够正确运行代码。去优化是不好的,因为它需要时间并且被替换的代码性能较低。

要查看此操作,请使用选项运行代码 --trace_opt --trace_opt_stats --trace_deopt --trace-内联

[deoptimize context: cbf30f14679]
[marking addText 0xcbf30fc5ca0 for recompilation, reason: small function, ICs with typeinfo: 1/1 (100%)]
[optimizing: addText / cbf30fc5ca1 - took 0.058, 0.092, 0.000 ms]
Compiled: 1 functions with 42 byte source size in 0.150000ms.
[marking addNumber 0xcbf30fc5ce8 for recompilation, reason: small function, ICs with typeinfo: 1/1 (100%)]
[optimizing: addNumber / cbf30fc5ce9 - took 0.019, 0.033, 0.000 ms]
Compiled: 2 functions with 84 byte source size in 0.202000ms.
[marking  0x2c9408e1b3d0 for recompilation, reason: not much type info but very hot, ICs with typeinfo: 1/12 (8%)]
Inlined addNumber called from .
Inlined addText called from .
[optimizing:  / 2c9408e1b3d1 - took 0.131, 0.229, 0.000 ms]
Compiled: 3 functions with 898 byte source size in 0.562000ms.
time1: 126ms
**** DEOPT:  at bailout #11, address 0x0, frame size 192
[deoptimizing: begin 0x2c9408e1b3d1  @11]
  translating  => node=111, height=32
    0x7fff72081080: [top + 104] <- 0x2c9408e1b4e9 ; [sp + 32] 0x2c9408e1b4e9 <an Object>
    0x7fff72081078: [top + 96] <- 0x58df1704121 <undefined> ; literal
    0x7fff72081070: [top + 88] <- 0x58df1704121 <undefined> ; literal
    0x7fff72081068: [top + 80] <- 0x58df1704121 <undefined> ; literal
    0x7fff72081060: [top + 72] <- 0x58df1704121 <undefined> ; literal
    0x7fff72081058: [top + 64] <- 0x58df1704121 <undefined> ; literal
    0x7fff72081050: [top + 56] <- 0x23522b3122be ; caller's pc
    0x7fff72081048: [top + 48] <- 0x7fff720810b0 ; caller's fp
    0x7fff72081040: [top + 40] <- 0x2c9408e1b0d9; context
    0x7fff72081038: [top + 32] <- 0x2c9408e1b3d1; function
    0x7fff72081030: [top + 24] <- 0x2c9408e1b389 ; [sp + 40] 0x2c9408e1b389 <JS Function add>
    0x7fff72081028: [top + 16] <- 0x2c9408e1b2f9 ; [sp + 48] 0x2c9408e1b2f9 <JS Function addText>
    0x7fff72081020: [top + 8] <- 0x2c9408e1b341 ; [sp + 56] 0x2c9408e1b341 <JS Function addNumber>
    0x7fff72081018: [top + 0] <- 0 ; rbx (smi)
[deoptimizing: end 0x2c9408e1b3d1  => node=111, pc=0x23522b364aa0, state=NO_REGISTERS, alignment=no padding, took 0.076 ms]
[removing optimized code for: ]
[marking add 0x2c9408e1b388 for recompilation, reason: small function, ICs with typeinfo: 1/1 (100%)]
[optimizing: add / 2c9408e1b389 - took 0.013, 0.024, 0.000 ms]
Compiled: 4 functions with 939 byte source size in 0.599000ms.
[marking  0x2c9408e1b3d0 for recompilation, reason: hot and stable, ICs with typeinfo: 2/12 (16%)]
Inlined addNumber called from .
Inlined addText called from .
Inlined add called from .
Inlined add called from .
[optimizing:  / 2c9408e1b3d1 - took 0.100, 0.194, 0.000 ms]
Compiled: 5 functions with 1753 byte source size in 0.893000ms.
time2: 1759ms

第一个循环由于参数更改而失去优化并且运行时间更长。这不能用缓存命中/未命中来解释,因为没有读/写。

来源: http://floitsch.blogspot.in/2012/03/optimizing-for-v8-inlining.html

关于V8 上的 JavaScript 测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20039587/

相关文章:

node.js - lodash 的 _.map 和 _.pluck 有什么区别?

javascript - 与 Bluebird 库取消 promise

javascript - 通过 String.prototype 函数设置字符串而不返回

javascript - 将 inline-flex 元素调整为屏幕宽度

javascript - 在`useEffect`中设置useEffect钩子(Hook)的依赖关系而不触发useEffect

ruby-on-rails - Gitlab CI 设置错误 - 找不到 JavaScript 运行时

node.js - NPM node-sass 安装失败

javascript - 返回在 POST 上创建的对象 - express.js

javascript - 使用 Knockout JS 过滤数据

javascript - onclick 传递数字和字符串