In fairness, the Java version had an easier path for optimization, but there are no free lunches.
Sounds like they were determined to write Python on Java. Doing it that way likely has a lot of performance costs. However, you can’t assume that idiomatic Java code would take that much longer than Python code for a team that was familiar with Java. Likely it comes down to which languages and frameworks a team is familiar with.
We used spring expression language for dynamic evaluation of (user-defined) expressions in our code and for most cases we could compile and cache the expressions after first usage and invoking them was really fast and close to pure java expressions.
We also had some JVM-python interop which we eventually got rid of (in favor of kotlin) because we were unable to optimize it after a month of effort and it continued to be the biggest bottleneck in the system.
So I am not entirely convinced that there could be real-world usage scenarios that inherently demands so much runtime dynamism that most benefits of JVM optimizations are nullified.
Of course, I'd love to be enlightened otherwise, but rather happy with JVM as of now.
Also, if you are looking for interop, then GraalVM might be worth a look — not the better-known AOT part, but the runtime one, which can seamlessly do interop between a number of languages, and it even optimizes between them!
What I intended to convey in my previous comment was that using strategies like pre-compilation (eg. Spring EL) it is possible to get good performance even for dynamic logic not known at runtime.
So I was curious what was so dynamic about this use case that JVM performance drops down to pythonesque level.
I don't want to speculate - maybe there is something that JVM is unable to optimize; maybe it is something weird happening in the library; or maybe python has gotten really better in recent past or this use case was able to benefit from some python lib with native bindings.
I’m pretty sure it was more than 10 years ago that Charles Nutter wrote a detailed description of why that wasn’t going to happen without breaking compatibility with Ruby, identifying the specific language features preventing that.
https://stefan-marr.de/papers/dls-marr-et-al-cross-language-...