-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Performance #8
Comments
I definitely didn't, and thank you for that BTW. The project started as an experiment to test the Kotlin Multiplatform feature, and ended up being the only way to support big numbers in multiplatform projects. I believe there's a "simple" workaround here, which could also be a wise design choice: I could make That should reduce the performance loss on the JVM. |
@danwallach can you provide the code of the benchmark you exploited to perform your performance assessment? I'm in the process of making I'd like to assess whether this change provokes an improvement in performance or not, before releasing it. It may also be useful for profiling. |
It was buried in a larger codebase. I'll see if I can extract something useful for you. Meanwhile, off topic, but I'm still trying to figure out the subtleties of multiplatform Kotlin, and it would be handy if you generated "IR" as well as "LEGACY" libraries. |
Okay, this was a bunch of fun to put together. This repo carves out the benchmark aspect of a much larger thing I'm working on. This particular repo is also JVM-only, although there's no reason that the kt-math part wouldn't work elsewhere.
|
FWIW: What I'm really working on is trying to build a common interface so that I can get java.math.BigInteger on the JVM or Android, Microsoft HACL* on Kotlin-Native, and I'm-not-sure-yet on JavaScript. HACL* is C code that was generated by a formally verified toolchain. It only supports 256-bit or 4096-bit bignum arithmetic, but that's exactly the only part I care about. For JavaScript, I was initially using |
Also FWIW, here are the results of running the benchmark on my 2013 MacPro (6-core Xeon, 3.5GHz):
The punchline seems to be, regardless of the acceleration tricks that I use, which replace modular exponentiation with multiplies out of a huge pre-computed table, we're talking about a 2-3x slowdown relative to |
In other news: my same benchmark, running with Kotlin/Native using Microsoft's HACL*, seems to run at 1/10 the performance of I haven't benchmarked Food for thought: how would you make |
Thanks for sharing. I will use that for benchmarking.
Have you considered using a profiler to understand which methods
Personally, I expect that Kotlin wastes a lot more time than Java because of null checks. |
However, I believe that attempting to optimize a generated code piece that was tailored on Java, may not be the best strategy. However, in principle, there is no reason not to rely on the original, well-performing, JVM classes behind the scenes. Of course, optimizations on other platforms will still be required. |
Agreed. The low-hanging fruit here is using java.math.BigInteger on JVM and Android, especially since the latter bottoms out in their SSL native code. I've looked at a few JavaScript libraries, but you inevitably run into async / promise APIs as in gmp-wasm. You'd have to make a high level decision to use suspend functions as part of the high level interface on every platform. For native code, I think the most performant library is going to be GMP. Meanwhile, you seem to have a difference between your library and java.math.BigInteger. To get the behavior of their "mod", I'm using your "rem". |
So I managed to get |
So I spent a few more days beating on trying to get |
A few new details that you may find relevant: Turns out, the modular exponentiation from the So far as I can tell, the |
I'm curious if you've looked at performance tuning. I built a relatively simple benchmark that just does ElGamal encryptions and decryptions, over and over, so lots of modular exponentiations, and I've found that, on my ~2013 MacPro:
GnuMP: ~200 ops/sec
Java's BigInteger: ~100 ops/sec
kt-math: ~33 ops/sec
That factor of three kinda hurts. I haven't (yet) gotten lost in detailed profiling of the code. The Java BigInteger code is doing the same things as kt-math, so it's really unclear what's going on.
The text was updated successfully, but these errors were encountered: