7

In certain versions of node, a += b is significantly slower than a = a + b, but similar in the browser and later versions. What causes them to run so differently?

  • node v6.10.0 (V8 5.1.281.93), 75% slower, or reverse is 4x faster
  • node v8.0.0 (V8 5.8.283.41), 86% slower, or reverse is 7x faster
  • node v8.2.1 (V8 5.8.283.41), 86% slower, or reverse is 7x faster
  • node v8.3.0 (V8 6.0.286.52), similar
  • node v8.7.0 (v8 6.1.534.42), similar
  • node v8.9.2 (V8 6.1.534.48), similar
  • chrome 62.0.3202.94 (V8 6.1.534.42), similar
  • safari 11.0.1, similar

Edit: found that it's related to node's v8 engine update from 5 to 6.

Snippet:

const iter = 10 * 1000 * 1000

function one() {
  let i = 0
  let sum = 0
  while (i < iter) {
    sum += i
    i++
  }
}

function two() {
  let i = 0
  let sum = 0
  while (i < iter) {
    sum = sum + i
    i++
  }
}

let time
const tries = 10

time = Date.now()
for (let i = 0; i < tries; i++) {
  one()
}
console.log('one: ' + String(Date.now() - time))

time = Date.now()
for (let i = 0; i < tries; i++) {
  two()
}
console.log('two: ' + String(Date.now() - time))
Billiam
  • 188
  • 1
  • 1
  • 8
  • 2
    Did you try switching the order of the tests `two` and `one`? _Homemade_ tests aren't always reliable. – ibrahim mahrir Dec 05 '17 at 23:49
  • what would that change? @ibrahimmahrir – Luca Kiebel Dec 05 '17 at 23:50
  • 1
    I've tried switching the order, "just because", but get the same result – Billiam Dec 05 '17 at 23:51
  • Looks like the bug is fixed, at least as of node v8.9.2 (V8 6.1.534.48) – Billiam Dec 05 '17 at 23:59
  • 1
    It's not "the bug" by definition. The standard does not guarantee they are implemented identically and have similar performance characteristics. Your benchmarks are unreliable: the function calls are invariant to the loop. – zerkms Dec 06 '17 at 00:00
  • Trying to find an answer to this lead me to the discovery that Github does not allow me to search for `"+="`, `"=="`, or `"+"` in a project. Apparently in any project, that is. – Max von Hippel Dec 06 '17 at 00:05
  • 1
    I've created a [**JSPerf test**](https://jsperf.com/assignment-plus-equal-vs-equal-plus/1). It is confirmed: `a += b;` is slower than `a = a + b;`. But not by a big margin though. – ibrahim mahrir Dec 06 '17 at 00:07
  • @ibrahimmahrir you can also copy paste this snippet into dev tools, get a result depending on your browser's JS interpreter – Billiam Dec 06 '17 at 00:10
  • @Billiam I've done that initially (in node, with reversing and everything) but as I said _not reliable_. – ibrahim mahrir Dec 06 '17 at 00:12
  • Sorry I read wrong, fixed the edit :) – Billiam Dec 06 '17 at 00:16
  • https://jsperf.com/assignment-plus-equal-vs-equal-plus/4 --- for me "nothing" is marginally (~2-10%) faster than either of those cases. Does it look trustworthy? – zerkms Dec 06 '17 at 00:23

1 Answers1

4

This is not an issue in Node, but with the V8 engine (which Node happens to use). There's a list of "bailout reasons" on the github page (github.com/vhf/v8-bailout-reasons), which are language constructs that kill optimization. "Unsupported let compound assignment", that is, compound assignment with let-bound variables, is one of them. If you profile the code in Chromium's dev tools, you should be able to see "Not optimized: Unsupported let compound assignment": https://i.stack.imgur.com/qBlp3.png

  • Some good news about v8 optimization (or fresh hope for better future): “All these optimization killers you learned throughout the years? Forget It You won't need them. Use whatever you want. Something still slow? File a bug! We'll fix it.” @bmeurer #jskongress Source: https://twitter.com/slsoftworks/status/930041069529690112 https://www.youtube.com/watch?time_continue=283&v=cvybnv79Sek – Jan aka uptech Dec 06 '17 at 17:25