3

I have some code which requires many Math.pow() function calls per second. In testing it seems to be a very large bottleneck to the performance of the code.

The results don't need to be precise - an accuracy of anywhere upwards of 85% should done fine - but my question would be is there any way I can somehow speed these calculations up? Maybe at the cost of some precision?

Edit: these calculations are very unlikely to repeat so a cache wouldn't work.

user11406
  • 1,208
  • 1
  • 13
  • 25
  • Is there anything in common between them (e.g. is the power always an integer or always the same)? – redbmk May 06 '15 at 18:29
  • @redbmk Yes, the power is always going to be an int between 2-5 – user11406 May 06 '15 at 18:31
  • 1
    can you please share us the relevant piece of code that does the Math.pow? Perhaps we can help you there, it's not very easy, unluckily, to directly guess what a faster solution could be. If we can't help you there, you might try codereview too, maybe some review masters may drastically reduce your code or find a more efficient way of doing maths, who knows! – briosheje May 06 '15 at 18:32
  • 1
    @user11406, there is a similar question for C/C++: http://stackoverflow.com/questions/2347138/fast-implementation-approximation-of-pow-function-in-c-c. Can it be helpful in JS? – DWand May 06 '15 at 18:33
  • 1
    I'm coming more from a C/C++ background as well as other performance-critical areas like GLSL, but we generally just avoid `pow` if we know the exponent in advance and it's small. Like instead of `pow(x, 2)`, just `x*x`. It's also rather idiomatic in this native territory to do things like: `float x2 = x*x; float x4 = x2*x2;`. I'd suggest this as a KISS strategy to using a function like `pow` which is really best-suited when the exponent is not known (varies at runtime) and/or large. –  May 06 '15 at 19:46
  • In some cases, if you have a fixed exponent, you can speed up things dramatically. I had to calculate `x^1.5`, and using `x*Math.sqrt(x)` turned out to be more than ten times faster than `Math.pow(x, 1.5)` – Waruyama Dec 02 '22 at 09:43

2 Answers2

4

at the cost of some precision

How much loss of precision? If you only need correct answers by a factor of 2, you could use bitwise manipulation.

function pow2(n) {
  return 2 << (n-1);
}

console.log(pow2(n) === Math.pow(2, n));

The Number constructor (including number literals) use only floating point numbers. This function converts the floats to 32-bit integers as described here.

Otherwise, I doubt you'll be able to beat the optimized native implementation of Math.pow.

twinlakes
  • 9,438
  • 6
  • 31
  • 42
0

jsPerf is a great tool for trying multiple techniques to find the fastest one.

This could vary quite a bit by browser or operating system, but so far it turns out that Math.pow is much faster in my environment (Chrome 42, 64-bit Linux) until you open up dev tools. With dev tools open, it's slightly faster to multiply the number as many times as you need depending on the power, as in the following example:

function pow(num, pow) {
    var result = num;
    while (--pow) {
       result *= num;
    }
    return result;
}

I'm running out of different ideas, but you can see what I have so far here:

http://jsperf.com/math-pow-alternatives

There is also a lot of overhead just to calling a function (hundreds of thousands of times). In this case it seems like Math.pow is the way to go, but there might be other ways to improve performance (or at least perceptible performance). If the code is blocking and the browser is experiencing some lag, you might try using web workers, or limiting the number of calculations per frame. You could also try to reduce the amount of function calls, or make sure you're interacting very minimally with the DOM (especially during the calculations, but preferably not at all).

Without a more concise code sample it will be difficult to fine-tune your code's performance.

redbmk
  • 4,687
  • 3
  • 25
  • 49
  • how would this work for square roots like Math.pow(2, 0.5) ? – B''H Bi'ezras -- Boruch Hashem Jul 07 '20 at 07:09
  • @bluejayke It wouldn't - so there's another limitation. Since `Math.pow` uses the JavaScript engine's native code it should generally be faster, and it's more complete than any of the other examples I gave, which I think all have the caveat that they only work with positive integers. – redbmk Jul 08 '20 at 19:36