Jas*_*onN 2 java performance jvm-hotspot
有没有人知道是否有办法从Java返回两个值(接近)零开销?我只是在寻找两个值 - 我有几个用例来处理一个字节数组(需要返回值和下一个起始位置)来尝试返回一个带有错误代码的值来做一些丑陋的修复 - 点计算并需要整个和小数部分.
我不低于一些非常丑陋的黑客.功能很小,Hotspot很高兴地介绍它.所以现在,我只需要让Hotspot基本上忽略任何对象创建或位移.
如果我将我的返回值限制为整数,我已经尝试将它们打包成长,但即使在内联之后,Hotspot似乎也无法弄清楚所有的位移和掩码都没有真正做任何事情而且它很乐意打包并解压缩注入相同的值(显然,Hotspot的窥孔优化器需要帮助的地方).但至少我不是在创造一个对象.
我更难的情况是,当我需要返回的项目之一是引用而另一个是长引用或另一个引用时(对于int情况,我认为我可以压缩OOP并使用上面描述的位填充).
有没有人试图让Hotspot为此生成无垃圾代码?现在最糟糕的情况是我必须携带一个物体然后传递它,但我想保持它自包含.线程本地是昂贵的(哈希查找),它需要是可重入的.
-XX:+EliminateAllocations 优化(在Java 8中默认为ON)可以正常工作.
无论何时new Pair(a, b)在callee方法结束时返回并在调用者中立即使用结果,如果被调用者被内联,JVM很可能会进行标量替换.
一个简单的实验表明返回一个对象几乎没有开销.这不仅是一种有效的方式,也是最具可读性的方式.
Benchmark Mode Cnt Score Error Units
ReturnPair.manualInline thrpt 30 127,713 ± 3,408 ops/us
ReturnPair.packToLong thrpt 30 113,606 ± 1,807 ops/us
ReturnPair.pairObject thrpt 30 126,881 ± 0,478 ops/us
ReturnPair.pairObjectAllocated thrpt 30 92,477 ± 0,621 ops/us
Run Code Online (Sandbox Code Playgroud)
基准:
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import java.util.concurrent.ThreadLocalRandom;
@State(Scope.Benchmark)
public class ReturnPair {
int counter;
@Benchmark
public void manualInline(Blackhole bh) {
bh.consume(counter++);
bh.consume(ThreadLocalRandom.current().nextInt());
}
@Benchmark
public void packToLong(Blackhole bh) {
long packed = getPacked();
bh.consume((int) (packed >>> 32));
bh.consume((int) packed);
}
@Benchmark
public void pairObject(Blackhole bh) {
Pair pair = getPair();
bh.consume(pair.a);
bh.consume(pair.b);
}
@Benchmark
@Fork(jvmArgs = "-XX:-EliminateAllocations")
public void pairObjectAllocated(Blackhole bh) {
Pair pair = getPair();
bh.consume(pair.a);
bh.consume(pair.b);
}
public long getPacked() {
int a = counter++;
int b = ThreadLocalRandom.current().nextInt();
return (long) a << 32 | (b & 0xffffffffL);
}
public Pair getPair() {
int a = counter++;
int b = ThreadLocalRandom.current().nextInt();
return new Pair(a, b);
}
static class Pair {
final int a;
final int b;
Pair(int a, int b) {
this.a = a;
this.b = b;
}
}
}
Run Code Online (Sandbox Code Playgroud)