Rob*_*bAu 12 java performance modulo primitive-types null-check
我试图从某些内部方法中获得尽可能多的性能。
Java代码是:
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
}
Run Code Online (Sandbox Code Playgroud)
在我的分析器中,我看到 1% 的 CPU 支出java.util.Objects.requireNonNull,但我什至不称之为。在检查字节码时,我看到了:
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
Run Code Online (Sandbox Code Playgroud)
所以编译器会生成这个(没用的?)检查。我在原语上工作,null无论如何都不能,那么编译器为什么会生成这一行?这是一个错误吗?还是“正常”行为?
(我可能会使用位掩码,但我只是好奇)
[更新]
运营商似乎与它无关(请参阅下面的答案)
使用 eclipse 编译器(4.10 版),我得到了更合理的结果:
public getParent(I)I 抛出 java/io/IOException
L0
LINENUMBER 77 L0
负载 1
图标_4
国际电联
2号店
L1
LINENUMBER 78 升
所以这更合乎逻辑。
假设
class C {
private final int taxos = 4;
public int test() {
final int a = 7;
final int b = this.taxos;
return a % b;
}
}
Run Code Online (Sandbox Code Playgroud)
c.test()像where这样的调用c被声明为 as ,当is时C 必须抛出。你的方法相当于cnull
public int test() {
return 3; // `7 % 4`
}
Run Code Online (Sandbox Code Playgroud)
因为您只使用常量。由于test是非静态的,因此必须进行检查。通常,当访问字段或调用非静态方法时,它会隐式完成,但您不这样做。因此需要进行显式检查。一种可能性是致电Objects.requireNonNull。
不要忘记字节码基本上与性能无关。的任务javac是生成一些字节码,其执行与源代码相对应。它并不意味着进行任何优化,因为优化后的代码通常更长且更难分析,而字节码实际上是优化 JIT 编译器的源代码。所以javac预计保持简单......
在我的分析器中,我看到有 1% 的 CPU 支出
java.util.Objects.requireNonNull
我首先会责怪分析器。分析 Java 非常困难,您永远无法期望完美的结果。
您可能应该尝试将该方法设为静态。您当然应该阅读这篇关于空检查的文章。