Hacker News new | ask | show | jobs
by kaba0 1328 days ago
I don’t really agree with these points regarding performance speed (of course AOT is a cool technology that has its uses):

> - in AOT 100% of the code is compiled

If the code hasn’t been run enough times to become eligible for JIT compilation, it likely doesn’t contribute any significant time to the whole runtime, so I doubt it would be a meaningful change.

> some optimizations are only possible under a closed-world assumption (AOT)

Which a JIT compiler is more than free to assume much more strictly than an AOT one can? Like, if it sees that only a single implementing class of an interface is loaded it can assume that every virtual method call can be replaced by a static one. Upon a class load, this assumption can be revisited and the native code can be deoptimized in cases. In an AOT compiler you have to optimize based on the worst case, while JIT compiler may avoid loading that class based on some dynamic property. Also, Graal is not only an AOT compiler, it is also a JIT compiler with.. closed-world assumptions, so it is quite meaningless comparison.

The last point is true on paper, but as far as I know it is not true that JIT compilers produce worse code, and even if it is it is not due to lack of time/resources.

But I just wanted to refute the performance claims — Graal Native executables do start up much faster and have significantly less memory usage, which are worthwhile goals in themselves. But most Java code will perform better under a JIT compiler (which can be Graal’s as well)

2 comments

  > " But most Java code will perform better under a JIT compiler (which can be Graal’s as well)"
This was my understanding, for any comparison of world-class JIT compilers vs AOT codegen. But, fniephaus knows his stuff and there are some compelling particular examples/benchmarks given. I haven't taken the time to do an exhaustive comparison.

It does seem sort of counterintuitive though, doesn't it? Like, what's the point of an optimizing JIT then?

I’m sure there are examples where Graal Native will beat the JIT version of the same program (e.g. it often does more throughout escape analysis, also, smaller object allow more data to fit inside cache, etc), but in case of a “typical” application I would wager that the JIT approach is better. Maybe that’s just the way idiomatic JVM code is written?
The problem with deoptimization is the performance hit every time it takes place, which leads to a saw graph similar to when there is too much GC going on.
Sure, but class loading only changes assumptions in one direction for example — in the aforementioned example it would cause only one deoptimization after which the code won’t be worse off than the AOT compiled one. So the JIT case before class load may perform better, and afterwards will perform the same.
Classes can also be unloaded.

What JIT does definitely better is when coupled with PGO data that survives between execution sessions.