RESOLVED FIXED284631
Math.hypot() is significantly slower than Math.sqrt()
https://bugs.webkit.org/show_bug.cgi?id=284631
Summary Math.hypot() is significantly slower than Math.sqrt()
Ashley Gullen
Reported 2024-12-13 07:17:11 PST
Created attachment 473562 [details] Performance benchmark 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. 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. Actual results: On an Apple M1 Pro with Safari 18.1.1, after three runs, the Math.sqrt() benchmark completes in ~39ms, and the Math.hypot() benchmark completes in ~181ms (~4.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.
Attachments
Performance benchmark (1.19 KB, text/html)
2024-12-13 07:17 PST, Ashley Gullen
no flags
Yusuke Suzuki
Comment 1 2024-12-16 16:26:14 PST
Right. We should lower Math.hypot into multiplication + sqrt.
Radar WebKit Bug Importer
Comment 2 2024-12-20 07:18:13 PST
Keita Nonaka
Comment 3 2025-03-17 07:25:50 PDT
Ashley Gullen
Comment 4 2025-03-17 07:31:58 PDT
That PR looks like it only optimizes for constant parameters - unfortunately that won't bring any real-world performance improvement, as in practice it is always going to be called with non-constant parameters (as per the benchmark).
Ashley Gullen
Comment 5 2025-03-17 07:34:21 PDT
Actually, I'm not so sure. Apologies if I got that wrong! Would be interested to see benchmark results.
Keita Nonaka
Comment 6 2025-03-20 02:05:26 PDT
I dont think hypot() becomes as fast as sqrt() because hypot function has overhead to avoid overflow or underflow. sqrt() is faster because it avoids overflow and underflow calculation, so in some cases, sqrt() does not calculate well. For example, ```js console.log(Math.hypot(1e308, 1e308, 1e308)) // 1.7320508075688772e+308 console.log(Math.sqrt(1e308 * 1e308 + 1e308 * 1e308 + 1e308 * 1e308)) // Infinity ``` https://www.typescriptlang.org/play/?#code/MYewdgziA2CmB00QHMAUBZAhgFwBb1wE8AHEbVARlgGYAGADgBoACKup1mhgSm4ChQkGAiRoseeBACOAJ3JsGzAFSd2zANTNVilQvobt+3V3q8gA
Keita Nonaka
Comment 7 2025-03-20 02:07:08 PDT
> NOTE > Implementations should take care to avoid the loss of precision from overflows and underflows that are prone to occur in naive implementations when this function is called with two or more arguments. https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-math.hypot
EWS
Comment 8 2025-03-22 18:56:44 PDT
Committed 292549@main (bdf66e673c2c): <https://commits.webkit.org/292549@main> Reviewed commits have been landed. Closing PR #42569 and removing active labels.
Note You need to log in before you can comment on or make changes to this bug.