Description
- Version: v12.18.4
- Platform: Linux 5.4.0-45-generic debugger: use requireRepl() to load debugger repl #49~18.04.2-Ubuntu SMP Wed Aug 26 16:29:02 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
- Subsystem: buffer.js
What steps will reproduce the bug?
I have not been able to create an isolated example outside of the application that reproduces the perf degradation - likely due to optimization.
When profiling our application (Cribl LogStream) we noticed that the top function call was a function called hidden
- after some digging it turns out that the call trace is something like this
Buffer.write
validateInt32
hideStackFrames
hidden
after modifying the application to all the undocumented Buffer.utf8Write
instead of Buffer.write
we see about 20% overall improvement and the heavy bottom profile looks like follows - note during both times the application was profiled for same amount of time (30s).
I noticed the same performance improvement after updating hideStackFrames to look like this:
function hideStackFrames (fn) { return fn; }
I have not been able to reproduce the perf degradation using a script that isolates just Buffer.write
operations. I don't even see the hidden
function calls at all during profiling. However, when I set a breakpoint in hideStackFrames
and then start profiling I do end up seeing hidden
in the profile - which make me think there's some optimization/compilation/inlinning issue at play.
UPDATE 9/28
I was able to repro the perf degradation by disabling inlining
buf$ node buffer.js
Buffer.write: 787.863ms
Buffer.utf8Write: 741.131ms
buf$ node --max-inlined-bytecode-size=0 buffer.js
Buffer.write: 1233.917ms
Buffer.utf8Write: 781.519ms
here's how buffer.js
looks like
const b = Buffer.alloc(1000*1000);
const str = '12345' + '67890';
console.time('Buffer.write');
let off = 0;
for(let i=0;i<1e7; i++) {
off += b.write(str, off);
if(off >= b.length) off = 0;
}
console.timeEnd('Buffer.write');
console.time('Buffer.utf8Write');
off = 0;
for(let i=0;i<1e7; i++) {
off += b.utf8Write(str, off);
if(off >= b.length) off = 0;
}
console.timeEnd('Buffer.utf8Write');
Could this mean that the default V8 inline settings are too conservative for the server side?