@Benchmark
public void testLambdaGeneration(Blackhole bh) {
Function<Object, Object> function = a -> {
if(a instanceof Alpha alpha) {
return alpha.primitiveInt();
}else {
throw new RuntimeException();
}
};
bh.consume(function);
}
@Benchmark
public void testManualGeneration(Blackhole bh) {
try{
MethodHandle mh = MethodHandles.lookup().findVirtual(Alpha.class, "primitiveInt", MethodType.methodType(int.class));
MethodType type = mh.type();
type = type.changeReturnType(Integer.class);
CallSite callSite = LambdaMetafactory.metafactory(MethodHandles.lookup(),
"apply",
MethodType.methodType(Function.class),
type.erase(), mh, type);
Function<Object, Object> f = (Function<Object, Object>) callSite.getTarget().invokeExact();
bh.consume(f);
}catch (Throwable e) {
throw new RuntimeException("Unreached");
}
}
我想使用 lambdametafactory 创建构造函数、getter 和 setter 方法以供反射使用,生成的 Function<> 与直接调用一样快,这极大地满足了我的需求。然而,当我使用上面的代码来测试 lambdafactory 和纯 lambda 之间的生成性能时,结果却相当不乐观:
LambdaTest.testLambdaGeneration avgt 50 0.574 ± 0.015 ns/op
LambdaTest.testManualGeneration avgt 50 29424.815 ± 20402.801 ns/op
我认为lambda函数内部会使用LambdaMetafactory,所以结果应该是一致的,但实际结果确实让我震惊。
我的代码有什么问题吗?如何提高 LambdaMetafactory.metafactory() 的性能以匹配纯 lambda 生成?
你可以试试我写的这个版本。
private Function<Object, Object> cachedFunction;
@Setup
public void setup() {
try {
MethodHandle mh = MethodHandles.lookup().findVirtual(Alpha.class, "primitiveInt", MethodType.methodType(int.class));
MethodType type = mh.type().changeReturnType(Integer.class);
CallSite callSite = LambdaMetafactory.metafactory(MethodHandles.lookup(),
"apply",
MethodType.methodType(Function.class),
type.erase(), mh, type);
cachedFunction = (Function<Object, Object>) callSite.getTarget().invokeExact();
} catch (Throwable e) {
throw new RuntimeException("Setup failed", e);
}
}
@Benchmark
public void testCachedManualGeneration(Blackhole bh) {
bh.consume(cachedFunction.apply(new Alpha()));
}