Hacker News new | ask | show | jobs
by lucb1e 2588 days ago
I did some testing with pypy, which also works with arbitrarily large integers but iirc does JIT instead of interpretation (like cpython would do), so that should be similar to JS in V8 except that it has arbitrarily large integers.

    a = Math.pow(2, 1023)
    t = new Date().getTime()
    for (var i = 0; i < 1e7; i++) {
        a += i;
    }
    console.log(new Date().getTime() - t);
vs

    a = pow(2, 1024)
    t = time.time()
    for i in range(int(1e7)):
        a += i
    print(time.time() - t)
Both ran a bunch of times: pypy does it in 279ms and nodejs in 250. I chose 1024 for Python because that is where JS starts to return infinity, so the JS code does operations on a number just below that. The time seems to be spent in the loop, as an empty loop or a loop doing a+=0 is 20x faster.

Lowering the exponent to 100, JS spends 269ms and pypy 142. Not sure why that is, but having arbitrarily large integers doens't seem to make this arithmetic any faster.

I don't know how to quickly toy around with fraction-based floats, but at least for arbitrarily large integers, I'm not sure why we're going to have to put up with new syntax.

2 comments

25 nanoseconds is much longer than a normal double-precision addition, loop counter increment, and conditional jump back to the top of a loop should take, so there's something other than the time taken by additions that's going on in your benchmark. I'm not a Node.JS expert, but I suspect it's not getting JITted properly, or getting poorly optimized if so.

I tried in C:

    #include <math.h>
    #include <stdio.h>
    int main()
    {
      double a = pow(2, 100);
      for (double i = 0; i < 1e7; ++i) {
        a += i;
      }
      printf("%f\n", a);
    }
and timed it. The time taken was 17ms.
Rearanged your js sample a bit, now it runs in ~26ms (first time) and ~11ms (subsequent times) instead of ~220ms in the chrome developer console.

    {
        let a = Math.pow(2, 1023)
        let t = performance.now();
        let max = 1e7;
        for (let i = 0; i < max; i++) {
         a += i;
        }
        console.log(performance.now() - t);
    }
Main problem was, that you should declare a with let.

That benchmark is a bit strange/flawed anyway. You're initializing a as pow(2, 1023), then adding numbers in the loop. But since a is already such a large double value, the result won't change. The numbers you add are too small to make a dent in the value of a, likely because a isn't an integer. It's a double with a limited precision for large integer values.