0

In the following code it is clear that baa is always false. Will the hotspot compiler spot this and remove the isBaa() method call and contained code?

public class Foo() {
    public final boolean baa = false;
    public isBaa() {
        return baa;
    }
}

Usage like this

static final Foo foo = new Foo();

public m() {
    if (foo.isBaa()) {
        // code here...
    }
}

I'd like to know if this code compares to adding

static final Foo foo = new Foo();
static final BAA = foo.isBaa();

and checking with

if (BAA) ...

Interested in runtime speed after hotspot has done its thing. Is there anyway to actually see what the result of hotspot compilation is? Or do we have to infer from the implementation details of the hotspot compiler being used.

The use case is to back isDebugEnabled() by a final variable in very performance sensitive code. So I'm interested in whether the method call itself is optimized out.

teknopaul
  • 6,505
  • 2
  • 30
  • 24
  • It may be more reliable to use a static final. – Dave Newton Sep 04 '17 at 12:45
  • Does "reliable" mean there are some situations this works and some it does not? – teknopaul Sep 04 '17 at 13:08
  • Not sure. I know for some impls that code wrapped with static finals can be completely removed, but that was a long time ago (and Android). The compiler will check for compile-time static values-it does no logical analysis, hence using a static final is guaranteed (?) to do what you'd expect. My *guess* is that a non-static wouldn't work at compile time (easy enough to check) but would be JITted after warmup. But sorry-I'm guessing :/ – Dave Newton Sep 04 '17 at 13:17

1 Answers1

0

Answering my own question...

I used timing to measure when hotspot has completely got rid of code. i.e. if code in a loop adds no more time to the loop execution time its been compiled out.

  • static final boolean checks can be completely compiled out.
  • static method calls can be compiled out.
  • instance methods, even if marked final, are not.

In my tests on ibm jdk8 final method calls that do nothing took ~6 clock cycles.

Hotspot docs from IBM imply that final instance methods can be inlined but testing indicates there is still a cost. I guess future VMs might be able to optimize this further.

In my tests it seems hotspot compilation also affects how loops are distributed across CPU cores.

for(; i < Integer.MAX_VALUE ; i++)

Is magically run across all 4 CPUs (avg time 1/4 of a clock cycle)

for(; i < Integer.MAX_VALUE ; i++) if (false) ...

Takes average 1 clock cycle

So even code that is hotspot compiled to nothing can affect optimizations of the surrounding code.

teknopaul
  • 6,505
  • 2
  • 30
  • 24
  • I would question your measuring methods. If you have a statement like `if(false) …`, it will be already removed *at compile-time*. Likewise, any variable declared like `final boolean baa = false;` is a *compile-time constant* and every read access is replaced by the value `false` *at compile time* already. The variable doesn’t have to be `static` for this. Whether the method is `final` or not has indeed no impact, as the JVM is smart enough to recognize that it hasn’t been overridden anywhere, to the outcome that it can be inlined in either case. – Holger Sep 05 '17 at 18:13
  • I recommend using `javap -c` to look at the bytecode. If there’s no difference in the bytecode, measuring different performance implies a problem with the benchmark. You can use `-XX:+PrintCompilation` at runtime to learn about what the JVM does and `-XX:+PrintAssembly` to see the results. If you google for these options, you’ll find a lot of resources on this topic. – Holger Sep 05 '17 at 18:17