8

I was creating a solution to an ICPC problem using JavaScript and Node.js when I ran into an interesting issue: under certain circumstances my program would run twice as slow on the same data set.

I stripped it down until I got to this minimal example that demonstrates the behavior:

function solve(arr) {
  const total = arr.reduce((a, c) => a + c, 0);
  const count = arr.length;
  for (let i = 0; i < total; i++) {
    for (let j = 0; j < count; j++) {
      // calculate some stuff
    }
  }
}

for (let i = 0; i < 10; i++) {
  // generate some sample data (array of 5000 random numbers 1-10)
  const data = [];
  for (let i = 0; i < 5000; i++) {
    data.push(Math.floor(Math.random() * 10) + 1);
  }

  const start = new Date();
  solve(data);  // run solve on the data
  console.log(`${i + 1}: ${new Date() - start}ms`);
}

This is the output of running node --trace-opt code.js using Node v10.15.1:

[marking 0x005062b82521 <JSFunction solve (sfi = 000001DA56AD8CD9)> for optimized recompilation, reason: small function, ICs with typeinfo: 5/7 (71%), generic ICs: 0/7 (0%)]
[compiling method 0x005062b82521 <JSFunction solve (sfi = 000001DA56AD8CD9)> using TurboFan OSR]
[optimizing 0x005062b82521 <JSFunction solve (sfi = 000001DA56AD8CD9)> - took 1.453, 0.702, 0.082 ms]
1: 86ms
[marking 0x005062b82581 <JSFunction (sfi = 000001DA56AD8BD9)> for optimized recompilation, reason: hot and stable, ICs with typeinfo: 22/23 (95%), generic ICs: 1/23 (4%)]
[compiling method 0x005062b82521 <JSFunction solve (sfi = 000001DA56AD8CD9)> using TurboFan]
[optimizing 0x005062b82521 <JSFunction solve (sfi = 000001DA56AD8CD9)> - took 0.159, 0.632, 0.096 ms]
2: 82ms
3: 80ms
[compiling method 0x005062b82581 <JSFunction (sfi = 000001DA56AD8BD9)> using TurboFan OSR]
[optimizing 0x005062b82581 <JSFunction (sfi = 000001DA56AD8BD9)> - took 0.592, 2.312, 0.154 ms]
4: 245ms
5: 243ms
6: 236ms
7: 237ms
8: 240ms
9: 246ms
10: 239ms

During the first three iterations the run time is around 80ms, but just before the fourth iteration Node recompiles and optimizes a method and from that point on the code runs about 3 times slower.

Typically when Node does runtime analysis, recompilation, and optimization everything runs faster.

Can anyone explain why Node optimization makes things so much worse in this case?


Note that if the example code is changed to calculate total by iterating instead of using reduce the optimization improves performance as expected (run time drops to around 60ms):

let total = 0;
for (let v of arr) total += v;
5
  • What about other parts? Maybe this 240ms and some other optimized part runs quicker overall? Perhaps other parallel jobs got a lot faster so 240ms is amortized? Commented Feb 27, 2019 at 15:37
  • 2
    I think you should report this as a bug, it's certainly unexpected. Commented Feb 27, 2019 at 18:15
  • @Bergi good point, didn't realize Math.random() excluded 1, code sample updated. Good idea, I'll open an issue. Commented Feb 27, 2019 at 18:41
  • If you did file a bug report, can you link it please? Commented Feb 28, 2019 at 18:12
  • 1
    @Bergi Node issue 26341, V8 issue 8922. Looks like it is caused by a known compiler issue in V8 and a fix is currently being tested. Commented Feb 28, 2019 at 18:27

1 Answer 1

1

I filed a bug report and got the following response from a Chromium dev:

Some array builtins used branch hints for loop bounds checks, causing all code after the inlined builtin to become deferred code. This is detrimental for performance.

So it turns out this is a known issue with the TurboFan compiler and a fix has been created and is currently being tested:

This CL removes the hints, which improves code scheduling a lot, on the micro benchmark from the linked bug by 3x.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.