I'm trying to get as much performance as possible from some internal method.
The Java code is:
List<DirectoryTaxonomyWriter> writers = Lists.newArrayList();
private final int taxos = 4;
[...]
@Override
public int getParent(final int globalOrdinal) throws IOException {
final int bin = globalOrdinal % this.taxos;
final int ordinalInBin = globalOrdinal / this.taxos;
return this.writers.get(bin).getParent(ordinalInBin) * this.taxos + bin; //global parent
}
In my profiler I saw there is 1% CPU spend in java.util.Objects.requireNonNull
, but I don't even call that. When inspecting the bytecode, I saw this:
public getParent(I)I throws java/io/IOException
L0
LINENUMBER 70 L0
ILOAD 1
ALOAD 0
INVOKESTATIC java/util/Objects.requireNonNull (Ljava/lang/Object;)Ljava/lang/Object;
POP
BIPUSH 8
IREM
ISTORE 2
So the compiler generates this (useless?) check. I work on primitives, which cannot be null
anyways, so why does the compiler generate this line? Is it a bug? Or 'normal' behaviour?
(I might work around with a bitmask, but I'm just curious)
[UPDATE]
The operator seems to be having nothing to do with it (see answer below)
Using the eclipse compiler (version 4.10) I get this more reasonable result:
public getParent(I)I throws java/io/IOException L0 LINENUMBER 77 L0 ILOAD 1 ICONST_4 IREM ISTORE 2 L1 LINENUMBER 78 L
So that is more logical.
Assuming
class C {
private final int taxos = 4;
public int test() {
final int a = 7;
final int b = this.taxos;
return a % b;
}
}
a call like c.test()
where c
is declared to as C
must throw when c
is null
. Your method is equivalent to
public int test() {
return 3; // `7 % 4`
}
as you work with constants only. With test
being non-static, the check must be done. Normally, it would get done implicitly when a field gets accessed or a non-static method gets called, but you don't do it. So an explicit check is needed. One possibility is to call Objects.requireNonNull
.
Forget not that the bytecode is basically irrelevant for the performance. The task of javac
is to produce some bytecode whose execution corresponds with your source code. It's not meant to do any optimizations, as optimized code is usually longer and harder to analyze, while the bytecode is actually the source code for the optimizing JIT compiler. So javac
is expected to keep it simple....
In my profiler I saw there is 1% CPU spend in
java.util.Objects.requireNonNull
I'd blame the profiler first. Profiling Java is pretty hard and you can never expect perfect results.
You probably should try making the method static. You surely should read this article about null checks.