我试图从一些内部方法中获得尽可能多的性能。
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
}
在我的分析器中,我看到
java.util.Objects.requireNonNull
中有 1% 的 CPU 开销。 ,但我什至不这么叫。在检查字节码时,我看到了这个: 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
所以编译器会生成这个(没用的?)检查。我研究原语,它不能是
null
无论如何,为什么编译器会生成这一行?它是一个错误吗?还是“正常”行为?(我可能会使用位掩码,但我只是好奇)
[更新]
public getParent(I)I throws java/io/IOException
L0
第 77 行 L0
加载 1
ICONST_4
IREM
存储 2
L1
LINENUMBER 78 L
所以这更合乎逻辑。
最佳答案
为什么不?
假设
class C {
private final int taxos = 4;
public int test() {
final int a = 7;
final int b = this.taxos;
return a % b;
}
}
像
c.test()
这样的电话在哪里 c
被声明为 C
必须抛出c
是 null
.你的方法相当于 public int test() {
return 3; // `7 % 4`
}
因为您只使用常量。与
test
由于是非静态的,因此必须进行检查。通常,当访问字段或调用非静态方法时,它会隐式完成,但您不这样做。所以需要明确的检查。一种可能是调用 Objects.requireNonNull
.字节码
不要忘记字节码基本上与性能无关。
javac
的任务是生成一些执行与您的源代码相对应的字节码。这并不是为了做任何优化,因为优化后的代码通常更长更难分析,而字节码实际上是优化 JIT 编译器的源代码。所以javac
预计会保持简单......表现
In my profiler I saw there is 1% CPU spend in
java.util.Objects.requireNonNull
我会先责怪分析器。分析 Java 非常困难,您永远无法期待完美的结果。
您可能应该尝试将方法设为静态。你当然应该阅读 this article about null checks .
关于java - int 上的余数运算符导致 java.util.Objects.requireNonNull?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60041522/