High cost of failed Math.*Exact calls
Remi Forax
forax at univ-mlv.fr
Fri Dec 13 08:15:24 UTC 2024
Hello,
as far as i remember, c2 is alble to transform a
try {
Math.somethingExact(...)
} catch(ArithmeticException e) {
...
}
to a jump on overflow ("jo") if the catch and the method call to Math.somethingExact() are in the same inlining horizon.
If you want a garantee that this optimization occurs, it means that you have to generate the catch in the same method blob.
One solution i've explored (10 years ago) but not pursue is to generate a code that the VM can de-optimize by itself without you having to generate a new code
[ https://github.com/forax/vmboiler | https://github.com/forax/vmboiler ]
In my case, in terms of performance, it was better when one exception was raised to trash the generated code and generate a new code only with Bignum (no Fixnum) so there is no overflow check anymore in the code.
regards,
Rémi
> From: "Charles Oliver Nutter" <headius at headius.com>
> To: "Core-Libs-Dev Libs" <core-libs-dev at openjdk.java.net>
> Sent: Thursday, December 12, 2024 11:58:32 PM
> Subject: High cost of failed Math.*Exact calls
> Hey folks, I was looking into a performance bug report for JRuby that did a lot
> of numeric work (a prime number detector) and ran into a bottleneck due to our
> use of Math.multiplyExact.
> Basically, the *Exact methods work great as long as you never actually overflow.
> If you overflow (too much), the cost of the exception raised massively
> outweighs any gains from avoiding the manual overflow check.
> I'm wondering two things at this point:
> Question one: Do we need to add versions of these methods that don't raise?
> Obviously we only have one return value, so the failure case needs to be
> communicated a different way. I'm thinking something like
> Math.multiplyExact(long a, long b, long failure) that will return the failure
> value for either an overflow or if the multiply produced that exact value. It
> would mean one value can never be produced through multiplyExact, but I think
> that's a tiny cost compared to raising an exception for all overflows.
> Of course you can do two of these in a row with different failure values to
> avoid falling back on BigInteger logic, and only 1 result out of 2**63 will
> have to multiply twice.
> Question two: Am I losing the benefits of *Exact if I use the following code to
> "pre-check" for overflow?
> long high = Math.multiplyHigh(a, b);
> if (high == 0) return Math.multiplyExact(a, b);
> return bigIntegerMultiply(a, b);
> Until there's a no-throw version of Math.*Exact I may have to go with this code.
> Charles Oliver Nutter
> Architect and Technologist
> Headius Enterprises
> [ https://www.headius.com/ | https://www.headius.com ]
> [ mailto:headius at headius.com | headius at headius.com ]
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20241213/f7cbba3a/attachment-0001.htm>
More information about the core-libs-dev
mailing list