gpt4 book ai didi

java - 测试 Java 反射、方法句柄和镜像性能

转载 作者:行者123 更新时间:2023-12-01 12:37:02 25 4
gpt4 key购买 nike

我正在测试方法句柄(随 Java 7 提供)相对于 Java 反射和镜像(使用反射的流畅 API - http://projetos.vidageek.net/mirror/mirror/ )的性能。所以我不知道我是否正确编写了测试代码。

我使用 JHM 工具进行此测试,并在要点中分享了代码和结果:https://gist.github.com/garcia-jj/057dcab7f388e5cb42d1

我在 setup 方法中缓存了所有查找以提高性能。

反射和方法句柄的最终时间几乎相等。

所以我的问题是:我的测试是正确的吗?我的应用程序中缓存方法查找存在一些问题?或者当我需要使用 invokeExact 时我需要始终查找?如果我不创建缓存,性能就会太低。

谢谢

@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 5, time = 1000, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 5, time = 1000, timeUnit = TimeUnit.MILLISECONDS)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Thread)
public class Reflecting {
// testing method handle
private MethodHandle mhConcat;
private MethodHandle mhHashCode;

// testing reflection
private Method rconcat;
private Method rhashcode;

// testing mirror api
private MethodHandler mrConcat;
private MethodHandler mrHashcode;

@Setup
public void setup() throws Exception {
mhConcat = publicLookup().findVirtual(String.class, "concat", methodType(String.class, String.class));
mhHashCode = publicLookup().findVirtual(Object.class, "hashCode", methodType(int.class));

rconcat = String.class.getDeclaredMethod("concat", String.class);
rhashcode = String.class.getDeclaredMethod("hashCode");

mrConcat = new Mirror().on((Object) "x").invoke().method("concat");
mrHashcode = new Mirror().on((Object) "xy").invoke().method("hashCode");
}

@GenerateMicroBenchmark
public void invoke(BlackHole bh) throws Throwable {
bh.consume((String) mhConcat.invokeExact("x", "y"));
bh.consume((int) mhHashCode.invokeExact((Object) "xy"));
}

@GenerateMicroBenchmark
public void reflect(BlackHole bh) throws Throwable {
bh.consume(rconcat.invoke("x", "y"));
bh.consume(rhashcode.invoke("xy"));
}

@GenerateMicroBenchmark
public void mirror(BlackHole bh) throws Throwable {
bh.consume(mrConcat.withArgs("y"));
bh.consume(mrHashcode.withoutArgs());
}
}

最佳答案

嗯,“错误”的定义通常始于“正确”的定义。假设您想通过不同的方式测量目标方法的调用成本,我可以列举一些可能需要注意的事项:

  1. @GenerateMicroBenchmark 建议您使用相当过时的 JMH(几个月前已重命名为 @Benchmark)。考虑更新以获得更可靠的线束版本。

  2. 使用 Blackhole-s 是值得尊敬的,但为什么每个 @Benchmark 有两个方法调用?您不想单独量化每个特定调用的性能吗?否则,您可能会冒用一种方法的性能改进掩盖另一种方法的性能下降的风险。拆分方法还有助于使用隐式 Blackhole-s(即从 @Benchmark 返回结果,而不是使用显式 Blackhole)。

  3. 基准测试无法阻止调用参数的可预测性,这可能会对被调用者内部的常量折叠进行一些测试。参见例如JMHSample_10_ConstantFold.java .

但最大的问题实际上是盲目相信数字。您应该实际检查是否出现问题,而不是在 StackOverflow 上要求其他人用他们神奇的眼光来猜测可能会出现什么问题!这将是更大问题的一部分:“为什么这些基准测试的性能彼此不同?”一旦你教会自己对每个基准提出这个问题,你就会拥抱基准测试之道:您应该对解释进行基准测试,而不是对数字进行基准测试。

要回答这些问题,您可以尝试:

  • 构建计算机如何工作以及代码如何与计算机交互的可信模型——这通常需要调整基准参数,并查看它是否按照当前模型预测的响应方式进行响应(看看它的响应方式有多自然)科学在这方面处理自然)。

  • 查看计算机操作内部,看看它在忙什么。使用分析器,卢克!现在,对于您在测试中进行的纳米级基准测试,并非所有分析器都很好。您可能必须认真研究生成的程序集和/或硬件计数器。环顾四周寻找一个。 JMH 附带了一个非常基本的 -prof perfasm

换句话说,探索!

关于java - 测试 Java 反射、方法句柄和镜像性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25487900/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com