9

I'm working on a javascript application that makes intensive use of math operations, dozens of calls per mouse move. I've been working on others' people code as a starting point, and I often find work arounds for the native javascript Math, such as...

var pi = Math.PI
var distance = (x * x) + (y * y) / R * R
var pixels = ~~(x/y)

Is there a significant performance hit for using the Math object? If so, what are some common workarounds?

methodofaction
  • 70,885
  • 21
  • 151
  • 164
  • 1
    Probably the `Math` methods are implemented in the language that javascript is implemented in (i.e. C or C++ in a typical browser) so they are much faster than what you can write in Javascript – Seth Carnegie Jan 16 '12 at 19:38
  • 5
    Have you **measured** the difference in performance? Across all your target browsers? – Greg Hewgill Jan 16 '12 at 19:39
  • 2
    Well `Math` doesn't have a "distance" method, and that integer conversion might be faster but it's also semantically different than `Math.floor()` or `Math.round()`. You can use [jsperf](jsperf.com) to test this sort of thing. – Pointy Jan 16 '12 at 19:39
  • Are you experiencing performance problems or is this a case of premature optimization? Assuming the former have you done any profiling? – Jordan Running Jan 16 '12 at 19:41
  • @SethCarnegie: Sure, if you're interpreting them. But any performance-sensitive JS *will* be compiled now, so x*x and Math.pow(x, 2) will be almost identical in terms of code-generated. – gsnedders Jan 16 '12 at 20:00
  • @Jordan the app has geometry happening in real-time as you move your mouse, so I'd like the best frame rate posible. I have no idea of how to do profiling in this case. – methodofaction Jan 16 '12 at 20:07

2 Answers2

17

If you are for some reason doing computing intensive stuff in javascript, you must remember those things (*and read David Mandelin's Know Your Engines: How to Make Your JavaScript Fast presentation - PDF, where he describes this in more details*):

  1. inline everything you can.

  2. function calls are very expensive

  3. object access is expensive

  4. polymorphism can cost you performance, your variables and arguments should always hold only one data type.

Math object is not especially slow, but you will not find distance() function there anyway, and accessing its methods from closure via Math.method() calls is, inefficient.

so sqrt is, of course, worse than x*x, custom random function might be better for you, Pi should be cached in loops, min and max should probably be avoided as well, no idea about trigonometry and logarithms speed.


P.S.: You can do things like ((x >= 0 ? x : -x) + 0.5) >> 0, to replace Math.ceil(Math.abs()), but remember - when i say "intensive" - i'm talking about number crunching, data processing, physics, graphics and things like that. For normal JavaScript sites or RIAs - you should not do stuff i am suggesting here. Also, most of the speed hacks have their side effects

Community
  • 1
  • 1
c69
  • 19,951
  • 7
  • 52
  • 82
  • 1
    Concerning point 4... I don't really understand. You cannot avoid duck typing in JS with objects, so you cannot avoid polymorphism with objects. A lookup is a lookup, so this looks to me the same as point 3. – Thomas Eding Jan 16 '12 at 20:29
  • 1
    Thanks for the tips, went through it and it seems there's more to be gained from architecture than micro-optimizations. My code is graphics related so I do need to squeeze out a bit of performance. – methodofaction Jan 17 '12 at 03:41
  • 1
    These are good points when one need to avoid expensive features of the language. In case one needs to avoid expensive Math calls here's my [Benchmark of Elementary Mathematical Operations in Node.js](https://www.akselipalen.com/2021/01/13/benchmark-of-elementary-mathematical-operations-in-node-js/) for starters. – Akseli Palén Jan 14 '21 at 21:43
0

I do not agree on the function calls. if statements inside if statements and long specialised functions is slower than well organised code with many small generalised functions.

Max
  • 281
  • 3
  • 11