top | item 39825727

(no title)

acimim_ha | 1 year ago

I don't really see why:

  public class TestJIT {
    public static void main(String[] args) {
        for (int i = 0; i < 20_000; i++) {
            payload();
        }
    }

    public static int payload(int a, int b) {
        return a + b;
    }
  }
shouldn't be optimized into a 'no-op'. The end-effect is the same.

discuss

order

mike_hearn|1 year ago

Things like that often will be, which is why you generally need to use the JMH harness to do microbenchmarking on the JVM. It uses internal APIs to stop the compiler treating results as dead and eliminating them.

In this case it doesn't happen because to see that the entire operation is dead requires the compiler to inline payload into main, but he says he disabled inlining for that method specifically so it wouldn't happen. Recall that the goal is to see the assembly for a block of code in isolation, not demo what the JVM can do when given free reign.

comonoid|1 year ago

Well, inlining is not necessary, good old interprocedure analysis would resolve it too.

neonsunset|1 year ago

There are two aspects to this:

- If payload is not inlined, the loop can't be optimized away. The fact of iteration itself may be a desirable side-effect (spin-wait/pause) a stricter compiler can't make an assumption about, unlike GCC or Clang

- If payload is inlined, it should be a no-op. If it's not, and its result consumed by an opaque "sink" method, there may be limitations.

On interproc analysis - don't forget you can dynamically load code and access payload through reflection too. This limits certain optimizations that are otherwise legal in AOT compilation. .NET has similar restrictions and corresponding differences when publishing binaries with JIT vs AOT - the former gets to enjoy DynamicPGO (HotSpot kind of optimizations), the latter gets to enjoy frozen world (with exact devirtualization, faster reflection, auto-sealing, etc. but overall not as good as DynamicPGO with guarded devirt, branch reordering, etc.).

munificent|1 year ago

Early in the article, the author tells the compiler not to inline calls to payload(). When that isn't inlined, the compiler can't tell if the body of the loop has side effects or not, so it won't be able to eliminate the loop.

hardware2win|1 year ago

Why would you want to remove those calculations?

You would change behavior of this program

acimim_ha|1 year ago

How? Except it would finish sooner. The is no behavior.