AOT Will Win

Ahead-of-time (AOT) compilation generally produces programs that run faster than just-in-time (JIT) compilation.

Why might a JIT be faster?

A JIT has strictly more information about the program: not just static analysis, but runtime data. This should enable additional optimisations and therefore speedups.

What do languages choose?

AOT is more common for the fastest programming languages. Some programming languages have moved from JIT to AOT (Java on Android, Cython), but I've not seen any PLs go from AOT to JIT.

Why can't JITs use the same optimisation techniques?

Up-front compilation is expensive, but you only do it once.

Compiler writers often find interesting optimisations they can run that take additional compute time. You can choose to optimise more aggressively, as long as the developer is willing to wait for the compiler.

What extra work is occurring?

Tracking the current state of the program requires compute that isn't doing useful work. You need to maintain counters to decide which bits to JIT compile. Even when you've JIT compiled code, you generally need to maintain guards to see if your runtime assumptions still hold.

JITs have disadvantages

Both AOT and JIT can have surprising performance cliffs. With JITs, this behaviour is dependent on runtime data. This makes it harder for developers to reproduce performance issues.

JITs can easily introduce startup costs too.

PGO has many JIT properties

Given a profile of how your program runs, you can optimise the compiled output accordingly. This gives you much of the JIT benefit, whilst still allowing the expensive optimisations.