aherbert commented on PR #139:
URL: https://github.com/apache/commons-numbers/pull/139#issuecomment-1868571519
Here are some benchmark results. JDK variants are prefixed with the class
that implements the method.
TLDR; the JDK is always faster for the int methods. It can be dramatically
slower for the long methods. They fixed this in JDK 17.
```
Tested using a MacBook Pro using an Apple M2 Pro CPU.
JDK 1.8.0_392, OpenJDK 64-Bit Server VM, 25.392-b08
ArithmeticPerformance.intOp 1024 Integer.divideUnsigned avgt 5
499.478 ± 14.720 ns/op
ArithmeticPerformance.intOp 1024 divideUnsigned avgt 5
765.350 ± 47.075 ns/op
ArithmeticPerformance.intOp 1024 Integer.remainderUnsigned avgt 5
500.030 ± 3.619 ns/op
ArithmeticPerformance.intOp 1024 remainderUnsigned avgt 5
771.374 ± 33.150 ns/op
ArithmeticPerformance.longOp 1024 Long.divideUnsigned avgt 5
9423.845 ± 2154.701 ns/op
ArithmeticPerformance.longOp 1024 divideUnsigned avgt 5
766.622 ± 41.090 ns/op
ArithmeticPerformance.longOp 1024 Long.remainderUnsigned avgt 5
15715.308 ± 3224.676 ns/op
ArithmeticPerformance.longOp 1024 remainderUnsigned avgt 5
730.340 ± 65.106 ns/op
JDK 11.0.21, OpenJDK 64-Bit Server VM, 11.0.21+9
Benchmark (length) (name) Mode Cnt
Score Error Units
ArithmeticPerformance.intOp 1024 Integer.divideUnsigned avgt 5
304.676 ± 1.188 ns/op
ArithmeticPerformance.intOp 1024 divideUnsigned avgt 5
572.168 ± 42.582 ns/op
ArithmeticPerformance.intOp 1024 Integer.remainderUnsigned avgt 5
315.873 ± 5.194 ns/op
ArithmeticPerformance.intOp 1024 remainderUnsigned avgt 5
549.925 ± 29.060 ns/op
ArithmeticPerformance.longOp 1024 Long.divideUnsigned avgt 5
26664.266 ± 13297.623 ns/op
ArithmeticPerformance.longOp 1024 divideUnsigned avgt 5
572.840 ± 44.454 ns/op
ArithmeticPerformance.longOp 1024 Long.remainderUnsigned avgt 5
10413.690 ± 1756.904 ns/op
ArithmeticPerformance.longOp 1024 remainderUnsigned avgt 5
547.748 ± 34.804 ns/op
JDK 17.0.9, OpenJDK 64-Bit Server VM, 17.0.9+9
ArithmeticPerformance.intOp 1024 Integer.divideUnsigned avgt 5
304.743 ± 2.939 ns/op
ArithmeticPerformance.intOp 1024 divideUnsigned avgt 5
595.448 ± 26.346 ns/op
ArithmeticPerformance.intOp 1024 Integer.remainderUnsigned avgt 5
312.449 ± 0.673 ns/op
ArithmeticPerformance.intOp 1024 remainderUnsigned avgt 5
547.708 ± 22.514 ns/op
ArithmeticPerformance.longOp 1024 Long.divideUnsigned avgt 5
418.294 ± 21.639 ns/op
ArithmeticPerformance.longOp 1024 divideUnsigned avgt 5
595.529 ± 28.412 ns/op
ArithmeticPerformance.longOp 1024 Long.remainderUnsigned avgt 5
438.290 ± 13.524 ns/op
ArithmeticPerformance.longOp 1024 remainderUnsigned avgt 5
499.466 ± 27.701 ns/op
```
It seems that performing the int divide using conversion to a long is faster
than the method to avoid long arithmetic. But the BigInteger divide was only
fixed in JDK 17.
I would recommend: dropping the int divide variants and delegating to the
JDK methods; and keeping the long divide variants. A note can be added to the
javadoc that the equivalent method in the JDK changed from JDK 11 to 17 to
avoid BigInteger arithmetic. I do not think we should add a deprecated notice
to the method until all supported versions of the JDK are comparable in speed.
Note: The int results would be more interesting on a CPU that does not
support native long division.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]