Node: v9.x seems to be slowing down ?

Created on 18 Nov 2017  路  9Comments  路  Source: nodejs/node

v9.x seems to be slowing down?
I have a computational function that performs benchmark tests in different versions of node.

// test function
function compute(w, v, s, k, f, vr1 = 1, vr2 = 0) {
    return s + (Math.max(v * vr2 || v / vr1, w) - f) * k;
}

Results are as follows:

(nodejs v7.9) 63,482,006 ops/sec 卤0.93% (90 runs sampled)
(nodejs v8.7) 539,999,198 ops/sec 卤0.48% (89 runs sampled)
(nodejs v8.9) 543,188,459 ops/sec 卤0.53% (91 runs sampled)
(nodejs v9.1) 487,698,977 ops/sec 卤0.64% (89 runs sampled)
V8 Engine performance v10.x

Most helpful comment

Thanks for the awesome repro. It seems that the loop peeling doesn't properly peel the loop in the bench function anymore.

Upstream issue: v8:7099

All 9 comments

Hi, @Lizhooh! Thank you for the information. Could you cite the complete runnable benchmark code?

cc @nodejs/performance, @nodejs/v8.

@vsemozhetbyt

const Benchmark = require('benchmark');
const suite = new Benchmark.Suite;

// test function
function compute(w, v, s, k, f, vr1 = 1, vr2 = 0) {
    return s + (Math.max(v * vr2 || v / vr1, w) - f) * k;
}

suite
    .add('my compute', function () {
        let result = compute(32, 27 / 1e6, 20, 3, 10, 1, 347);
    })
    .on('cycle', function (event) {
        console.log(String(event.target));
    })
    .run({ 'async': true });

@Lizhooh Thank you. It seems this pattern does slow down even more with the next V8 versions. My results on Windows 7 x64:

Node.js 8.9.1 (V8 6.1)
my compute x 271,200,039 ops/sec 卤0.16% (100 runs sampled)

Node.js 9.2.0 (V8 6.2)
my compute x 259,525,541 ops/sec 卤0.73% (91 runs sampled)

Node.js 9.0.0 (V8 6.3) canary
my compute x 132,483,285 ops/sec 卤0.16% (104 runs sampled)

Node.js 10.0.0 (V8 6.4) canary
my compute x 132,412,275 ops/sec 卤0.22% (105 runs sampled)

I hope @nodejs/v8 will chime in with some info.

The perf difference appears to be mostly coming from the calculation for the first argument of Math.max(), v * vr2 || v / vr1.

I think I've reduced the repro to the following:

'use strict';

function run(i) {
  const v = 0.1; // Important #1: Must be < 1.0 (>= 1.0 seems fine)
  return (
    (v * 1.0) || // Important #2: Can be any value, but must perform some operation like add/sub/mult/divide
    (v * 1.0)    // Important #3: Can be any value, but must perform some operation like add/sub/mult/divide
  );
}

function bench(iters) {
  let result = 0;
  for (let iter = 0; iter < iters; iter++) {
    result += run(iter);
  }
  return result;
}

const start = performance.now();
bench(1e7);
const end = performance.now();
console.log(end - start);

Comparing 6.1-lkgr fe8c059def and master aae52f6b0f

| | Before | After | Change |
|--------|--------|-------|-------------|
| | 12.42ms | 45.85ms | 0.27x |

@bmeurer

Thanks for the awesome repro. It seems that the loop peeling doesn't properly peel the loop in the bench function anymore.

Upstream issue: v8:7099

Link is broken

Not much left to do here.

Was this page helpful?
0 / 5 - 0 ratings