Remember what I always advise: always use the JS++ Standard Library if you can. The methods aren’t just well-tested for validity, but we also test for performance.
Checking if a number is even or odd is the classic fizzbuzz test. Most professional developers can use the modulus operator. However, that’s not always the fastest implementation.
> var t = new Date(); var x; for (var i = 0; i < 50000000; ++i) x = (i & 1) == 0; console.log(x); new Date - t; false 87 > var t = new Date(); var x; for (var i = 0; i < 50000000; ++i) x = (i & 1) == 0; console.log(x); new Date - t; false 90 > var t = new Date(); var x; for (var i = 0; i < 50000000; ++i) x = (i & 1) == 0; console.log(x); new Date - t; false 86 > var t = new Date(); var x; for (var i = 0; i < 50000000; ++i) x = (i & 1) == 0; console.log(x); new Date - t; false 86 > var t = new Date(); var x; for (var i = 0; i < 50000000; ++i) x = (i & 1) == 0; console.log(x); new Date - t; false 86 = 87ms > var t = new Date(); var x; for (var i = 0; i < 50000000; ++i) x = (i % 2) == 0; console.log(x); new Date - t; false 105 > var t = new Date(); var x; for (var i = 0; i < 50000000; ++i) x = (i % 2) == 0; console.log(x); new Date - t; false 100 > var t = new Date(); var x; for (var i = 0; i < 50000000; ++i) x = (i % 2) == 0; console.log(x); new Date - t; false 100 > var t = new Date(); var x; for (var i = 0; i < 50000000; ++i) x = (i % 2) == 0; console.log(x); new Date - t; false 104 > var t = new Date(); var x; for (var i = 0; i < 50000000; ++i) x = (i % 2) == 0; console.log(x); new Date - t; false 101 = 102ms Node.js v8.11.1 Linux x64 Core i7-4790k, 32gb RAM
var t = new Date(); var x; for (var i = 0; i < 5000000; ++i) x = (i & 1) == 0; console.log(x); console.log(new Date - t); false debugger eval code:1:80 1948 debugger eval code:1:96 var t = new Date(); var x; for (var i = 0; i < 5000000; ++i) x = (i & 1) == 0; console.log(x); console.log(new Date - t); false debugger eval code:1:80 2072 debugger eval code:1:96 var t = new Date(); var x; for (var i = 0; i < 5000000; ++i) x = (i & 1) == 0; console.log(x); console.log(new Date - t); false debugger eval code:1:80 2086 debugger eval code:1:96 var t = new Date(); var x; for (var i = 0; i < 5000000; ++i) x = (i & 1) == 0; console.log(x); console.log(new Date - t); false debugger eval code:1:80 2092 debugger eval code:1:96 var t = new Date(); var x; for (var i = 0; i < 5000000; ++i) x = (i & 1) == 0; console.log(x); console.log(new Date - t); false debugger eval code:1:80 2102 = 2060ms var t = new Date(); var x; for (var i = 0; i < 5000000; ++i) x = (i % 2) == 0; console.log(x); console.log(new Date - t); false debugger eval code:1:80 2058 debugger eval code:1:96 var t = new Date(); var x; for (var i = 0; i < 5000000; ++i) x = (i % 2) == 0; console.log(x); console.log(new Date - t); false debugger eval code:1:80 2082 debugger eval code:1:96 var t = new Date(); var x; for (var i = 0; i < 5000000; ++i) x = (i % 2) == 0; console.log(x); console.log(new Date - t); false debugger eval code:1:80 2114 debugger eval code:1:96 var t = new Date(); var x; for (var i = 0; i < 5000000; ++i) x = (i % 2) == 0; console.log(x); console.log(new Date - t); false debugger eval code:1:80 2102 debugger eval code:1:96 var t = new Date(); var x; for (var i = 0; i < 5000000; ++i) x = (i % 2) == 0; console.log(x); console.log(new Date - t); false debugger eval code:1:80 2104 debugger eval code:1:96 = 2092ms Firefox 59.0.2, Linux x64 Core i7-4790k, 32gb RAM
While the results are not statistically significant in Firefox (because it's very possible SpiderMonkey is manually optimizing this case via a pattern-matched optimization), you can get a 17% performance gain in Node.js via bitwise AND.
Due to all the layers of abstraction in JavaScript, it's not entirely evident how much faster a bitwise AND for isEven/isOdd can really be. In our benchmarks, we were able to achieve a 17% performance improvement in Node.js. As our lead engineer pointed out via email, according to this table, "for Intel Skylake-X `div` has a latency of 26 (for 32-bit integers), whereas `and` has latency 1 ("reciprocal throughput" has similar difference) so it is an order of magnitude slower, not 20% as in your tests."
Look for isEven()
and isOdd()
to appear in a future version of the JS++ Standard Library.
You may also be interested in reading Part II of this post which describes how we leveraged overflow behavior to improve performance while preserving correctness for UInteger32.