How to find Node.js Performance Optimization Killers
Vladimir de Turckheim
Lead Node.js engineer @ Sqreen (ex. Steamulo, Secway)
Outline
- Introduction: V8?
- Anatomy of an optimization...
- ... followed by a deoptimization
- Non-optimization
- Conclusion
V8?
V8 is a key component of Node.js: it executes the JS code
V8 dates
- 2008: Release
- 2010: Crankshaft
- 2015-2017: TurboFan
- 2017: Ignition
In V8, the code is optimized dynamically; this means that the code is optimized according to its runtime behavior.
Credit: Google
Credit: Google
In this talk we will focus on the pre-Ignition versions of V8
Anatomy of an optimization...
// index.js
function myFunc(nb) {
return nb + nb;
}
for (let i = 0; i < 2000; ++i) {
myFunc(i);
}
$ node --trace-opt index.js | grep myFunc
[marking 0x2bc3091e7fc9 <JS Function myFunc (SharedFunctionInfo 0x1866a5c5eeb1)>
for recompilation, reason: small function, ICs with typeinfo: 1/1(100%),
generic ICs:0/1(0%)]
[compiling method 0x2bc3091e7fc9 <JS Function myFunc (SharedFunctionInfo 0x1866a5c5eeb1)>
using Crankshaft]
[optimizing 0x2bc3091e7fc9 <JS Function myFunc (SharedFunctionInfo 0x1866a5c5eeb1)> -
took 0.009, 0.068, 0.036 ms]
[completed optimizing 0x2bc3091e7fc9 <JS Function myFunc (SharedFunctionInfo
0x1866a5c5eeb1)>]
The method's behavior is stable, it can be optimized.
... followed by a deoptimization
// index.js
function myFunc(nb) {
return nb + nb;
}
for (let i = 0; i < 2000; ++i) {
myFunc(i);
}
for (let i = 0; i < 2000; ++i) {
myFunc(i + '');
}
$ node --trace-opt --trace-deopt index.js | grep myFunc
[marking 0xc6b3e5e7fb9 <JS Function myFunc (SharedFunctionInfo 0x87d8115eec1)>
for recompilation, reason: small function, ICs with typeinfo: 1/1 (100%),
generic ICs: 0/1 (0%)]
...
[deoptimizing (DEOPT eager): begin 0xc6b3e5e7fb9 <JS Function myFunc
(SharedFunctionInfo 0x87d8115eec1)> (opt #0) @1, FP to SP delta: 24, caller sp: 0x7ffe2cde6f40]
reading input frame myFunc => node=4, args=2, height=1; inputs:
0: 0xc6b3e5e7fb9 ; [fp - 16] 0xc6b3e5e7fb9 <JS Function myFunc
(SharedFunctionInfo 0x87d8115eec1)>
translating frame myFunc => node=4, height=0
0x7ffe2cde6f10: [top + 0] <- 0xc6b3e5e7fb9 ; function
0xc6b3e5e7fb9 <JS Function myFunc (SharedFunctionInfo 0x87d8115eec1)> (input #0)
Deoptimization-hell ?
Non-optimization
Those are subject to change in latest versions of V8
// try.js
function myFunc(nb) {
try {
return nb + nb;
}
catch (err) {
return err;
}
}
for (let i = 0; i < 2000; ++i) {
myFunc(i);
}
$ node --trace-deopt --trace-opt try.js | grep myFunc
[disabled optimization for 0x3a450705eeb1 <SharedFunctionInfo myFunc>,
reason: TryCatchStatement]
Conclusion
V8 is not complicated to understand
JavaScript might be a permissive language, V8 does not like that
Turbofan will change the game for non-optimizations
What about chakracore ?
Going further
Any questions?
How to find Node.js Performance Optimization Killers
By Vladimir de Turckheim
How to find Node.js Performance Optimization Killers
- 946