I was benchmarking some of my own kotlin code vs B...
# mathematics
a
I was benchmarking some of my own kotlin code vs BigInteger to test performance. In doing so I eventually copied the BigInteger.java source to my own project so I could edit some things. Without any changes that was running about 2-3x slower at least for multiplication (same speed as my kotlin algorithms). Is there any explanation on why there is a speed difference using the library directly vs source code I imported from it?
a
First of all, how are you benchmarking? Do you use jmh?
a
Just running code with a diff on start/end time, there is some variation like 10% each run but at least for this case its consistently about 3x slower regardless of parameters I change or total runtime. I know not the most accurate but at least shows where obvious performance gaps are in early stages. The addition/subtraction are roughly equal so this only happens when its no longer O(n).
a
You won't get proper results with simple start/stop/. For example do you control when your classes are being loaded? Or deoptimizaion loops?
a
Will give that a try and report back later
Benchmark Mode Cnt Score Error Units Benchmark.javaBigInteger thrpt 5 527459.151 � 2535.441 ops/s Benchmark.javaBigInteger2 thrpt 5 255881.576 � 4363.851 ops/s Benchmark.sourceBigInteger thrpt 5 136094.088 � 5642.603 ops/s
Used java only for this, test was multiplying 2 BigInteger with an underlying array size of 75 (slightly under threshold for karatsuba algorithm)
javaBigInteger = java.math.BigInteger javaBigInteger2 = the same multiplication done twice, just to help me read the results correctly since its 2x slower sourceBigInteger = BigInteger.java source code copied to my project + any dependency files it needed
So just trying to figure out why the 1st and 3rd test have that much difference when it should be the same code running, is there some optimization built in to the core java libraries that you lose when using the source directly?
a
It is strange indeed. There should be no "optinizations" there. I would like to see your souce and to know which JVM are you using?
a
I need to clean some stuff up but will add to github eventually
AdoptOpenJDK (build 11.0.9+11)
My original kotlin project is using 1.8.0_111-b14
a
You can try running it on GraalVM. It is only my guess but I think You are boxing values somewhere and Graal is very good in mitigating this.
a
The other code is just this which I copied from src.zip in my jdk directory https://github.com/asheragy/BigInteger-Benchmark/tree/master/src/main/java/org/cerion/math/benchmark
a
Looks strange. There are several possibilities here: • The actual version of JDK you are using for benchmark is different from the one you take code from • For some reason generated bytecode for this class is better in compiled version than in the one produced by JDK
a
I only have 2 JDK versions installed so the source should match at least one I ran on (ran on both with same results). The generated bytecode sounds most likely although I am not sure how that is done, is there a way to produce a more optimized output?
a
Interesting. But we found out that pure kotlin implementation is still faster than java SDK even with a cheat
a
which implementation is that?
a
I meant https://github.com/mipt-npm/kmath/blob/dev/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt, but after the latest changes it is not faster than JVM anymore. A bit slower, but not much.
You can talk with @Zhelenskiy, who PRed the latest changes to the algorithm.
We are still missing BigDecimals by the way.
z
And we still don't use FFT for multiplying big ints.
a
one issue is the BigInt benchmark is testing squaring of a much larger number so multiplyToLen may not even be getting used so the jvm optimization doesn't apply there
a
@Andrew you are welcome to discuss it with @Zhelenskiy. PRs are welcome (especially if you also would implement missing BigDecimal (https://github.com/mipt-npm/kmath/issues/129). I run benchmarks yesterday and saw a small degrading of performance on GraalVM relative to older tests, but it is small enough to ignore it. On the other hand, current design is multiplatform and in my opinion much more compact and concise than the one in JDK.
An interesting thing about BigInt is that it has almost no input from KMath core developers and was fully contributed by external people. It is nice when someone else works on the code once in a while.
a
might be able to look at BigDecimal eventually, need to get that working in my own project first, have only done BigInteger so far since that is needed first