Math.hypot() is 9x slower than Math.sqrt() (We are overall faster than Chrome)
Categories
(Core :: JavaScript Engine, defect, P3)
Tracking
()
People
(Reporter: ashley, Unassigned)
References
(Blocks 1 open bug)
Details
Attachments
(1 file)
1.19 KB,
text/html
|
Details |
User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:133.0) Gecko/20100101 Firefox/133.0
Steps to reproduce:
Math.hypot() appears to be significantly slower than Math.sqrt(). As it is a more convenient specialized method for calculating the hypotenuse, this makes it easy to write code that is accidentally less performant than expected. This affects our browser-based game engine Construct (https://www.construct.net) as well as third-party math libraries like glMatrix (who eventually realized the same thing and removed uses of Math.hypot(): https://github.com/toji/gl-matrix/commit/8962b2e7727594022e59e48e605049c69403da60)
See attachment for what I believe is a fair benchmark.
Actual results:
On my machine after three runs, the Math.sqrt() benchmark completes in ~34ms, and the Math.hypot() benchmark completes in ~201ms (~6x slower).
Expected results:
Both benchmarks should complete in a similar time. If anything perhaps Math.hypot() should be faster, as more of the calculation is completed with a built-in method.
Note that optimizing the case where 2 or 3 arguments are passed should be sufficient to optimize the majority of performance-sensitive uses in game engines using 2D and 3D calculations.
Updated•2 months ago
|
Comment 2•2 months ago
•
|
||
Nightly:
Sqrt : 57msm 54ms, 59ms
hypot: 415ms, 411ms,414ms
Profile: https://share.firefox.dev/41xx0Ga (1.5 seconds)
Chrome:
Sqrt : 245ms, 247ms, 249ms
hypot: 491ms, 495ms,477ms
Profile: https://share.firefox.dev/3ZTAamH (2.4 seconds)
Updated•2 months ago
|
Comment 3•2 months ago
|
||
I think we're just faster than Chrome, because our Math.random
is faster.
Comment 4•2 months ago
|
||
For Math.sqrt
we use the sqrt
CPU instruction directly.
We specialize Math.hypot
with 2-4 arguments, but we currently always do a call to C++ code. For two arguments we call ecmaHypot
which calls fdlibm_hypot
, and we have a different implementation if there are more than two arguments.
To fix this we could change ecmaHypot
to use hypot_step
too. It should then be possible to inline the same code in the JITs, but it's a lot more machine code than add
+ sqrt
so it'll likely still be slower.
Comment 5•2 months ago
|
||
Replacing the fdlibm_hypot
call with the equivalent of hypot4
but for two arguments is slower for me in the JS shell, but that seems to be mainly because Clang didn't inline the std::isinf
/std::isnan
calls.
Updated•2 months ago
|
Updated•2 months ago
|
Description
•