注意:这是关于性能问题的而不是。我只观察到性能上的差异,我无法解释/理解。
当对一些针对Java 9的新开发代码进行基准测试时,我发现了一些奇怪的东西。一个带有5个键的(非常)简单的HashMap基准测试显示,Java9比Java8慢得多。这可以解释吗?还是我的(基准)代码完全错了?
代码:
@Fork(
jvmArgsAppend = {"-Xmx512M", "-disablesystemassertions"}
)
public class JsonBenchmark {
@State(Scope.Thread)
public static class Data {
final static Locale RUSSIAN = new Locale("ru");
final static Locale DUTCH = new Locale("nl");
final Map<Locale, String> hashmap = new HashMap<>();
public Data() {
hashmap.put(Locale.ENGLISH, "Flat flashing adjustable for flat angled roof with swivel");
hashmap.put(Locale.FRENCH, "Solin pour toit plat inclinée");
hashmap.put(Locale.GERMAN, "Flachdachkragen Flach Schrägdach");
hashmap.put(DUTCH, "Plakplaat vlak/hellend dak inclusief glijschaal");
hashmap.put(RUSSIAN, "Проход через плоскую кровлю регулир. для накл. кровли");
}
}
@Benchmark
public int bmHashMap(JsonBenchmark.Data data) {
final Map<Locale, String> m = data.hashmap;
int sum = 0;
sum += m.get(Data.RUSSIAN).length();
sum += m.get(Locale.FRENCH).length();
sum += m.get(Data.DUTCH).length();
sum += m.get(Locale.ENGLISH).length();
sum += m.get(Locale.GERMAN).length();
return sum;
}
}结果:
更新
谢谢你的回答和评论。
String#length()函数进行基准测试,则性能没有显著差异。而且,当我只对HashMap#get()方法(如@Eugene所建议的)进行基准测试时,仍然存在10-12 %的差异。发布于 2017-10-28 17:34:38
您正在测试的不仅仅是HashMap。您不仅调用了HashMap.get,还隐式地调用了Locale.hashCode和Locale.equals。此外,您正在调用String.length。
现在,这四种方法都可以改变它们的性能特性,因此您需要更多的测试来推断哪种方法表现出不同的性能。
但最热门的候选人是String.length。在Java9中,String类不再使用char[]数组,而是使用byte[]数组来编码拉丁1字符串,每个字符仅使用一个字节,大大减少了典型应用程序的内存占用。然而,这意味着长度并不总是与数组长度相同。因此,这一操作的复杂性发生了变化。
但是请记住,在一个微基准中,您的结果大约是77 ns。这不足以估计对实际应用程序…的影响。
发布于 2017-10-28 21:18:56
我曾暗示这是关于jmh的设置,而不是关于HashMap的。如前所述,您在这里测量的不仅仅是HashMap::get。但即使如此,我仍然怀疑java-9是否会慢得多,所以我对自己进行了评估(最新的jmh构建来源是java-8和9)。
我没有更改您的代码-只是添加了更多的堆(10‘t)和更多的热身,从而减少了您在±之后看到的“错误”。
使用java-8:
Benchmark Mode Cnt Score Error Units
SOExample.bmHashMap avgt 25 22.059 ± 0.276 ns/op使用java-9:
Benchmark Mode Cnt Score Error Units
SOExample.bmHashMap avgt 25 23.954 ± 0.383 ns/op结果几乎没有一个明显的差别(毕竟是纳米秒),正如你看到的。另外,如果您真的想测试HashMap::get,那么您的方法就可以简单地返回该调用,如下所示:
@Benchmark
@Fork(5)
public int bmHashMap(SOExample.Data data) {
return data.hashmap.get(data.key); // where key is a random generated possible key
}https://stackoverflow.com/questions/46988645
复制相似问题