首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >HashMap性能比Java 8低9 25%?

HashMap性能比Java 8低9 25%?
EN

Stack Overflow用户
提问于 2017-10-28 10:23:20
回答 2查看 2.7K关注 0票数 9

注意:这是关于性能问题的而不是。我只观察到性能上的差异,我无法解释/理解。

当对一些针对Java 9的新开发代码进行基准测试时,我发现了一些奇怪的东西。一个带有5个键的(非常)简单的HashMap基准测试显示,Java9比Java8慢得多。这可以解释吗?还是我的(基准)代码完全错了?

代码:

代码语言:javascript
复制
@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;
    }    

}

结果:

  • Java 8_151: JsonBenchmark.bmHashMap触发40 47948546.439±560763.711 ops/s
  • Java 9_181: JsonBenchmark.bmHashMap触发40 34962904.479±276045.691 ops/s (-/- 27%!)

更新

谢谢你的回答和评论。

  1. @Holger的建议。我的第一反应是:这一定是解释。但是,如果我只对String#length()函数进行基准测试,则性能没有显著差异。而且,当我只对HashMap#get()方法(如@Eugene所建议的)进行基准测试时,仍然存在10-12 %的差异。
  2. 作者建议:@Eugene.我更改了参数(更多的热身迭代,更多的内存),但我无法重现您的结果。不过,我把堆增加到了4G。但这不能解释不同之处,不是吗?
  3. 题名/责任者: by L.是的,这提高了性能!不过,差距仍在20%左右。
EN

回答 2

Stack Overflow用户

发布于 2017-10-28 17:34:38

您正在测试的不仅仅是HashMap。您不仅调用了HashMap.get,还隐式地调用了Locale.hashCodeLocale.equals。此外,您正在调用String.length

现在,这四种方法都可以改变它们的性能特性,因此您需要更多的测试来推断哪种方法表现出不同的性能。

但最热门的候选人是String.length。在Java9中,String类不再使用char[]数组,而是使用byte[]数组来编码拉丁1字符串,每个字符仅使用一个字节,大大减少了典型应用程序的内存占用。然而,这意味着长度并不总是与数组长度相同。因此,这一操作的复杂性发生了变化。

但是请记住,在一个微基准中,您的结果大约是77 ns。这不足以估计对实际应用程序…的影响。

票数 11
EN

Stack Overflow用户

发布于 2017-10-28 21:18:56

我曾暗示这是关于jmh的设置,而不是关于HashMap的。如前所述,您在这里测量的不仅仅是HashMap::get。但即使如此,我仍然怀疑java-9是否会慢得多,所以我对自己进行了评估(最新的jmh构建来源是java-8和9)。

我没有更改您的代码-只是添加了更多的堆(10‘t)和更多的热身,从而减少了您在±之后看到的“错误”。

使用java-8:

代码语言:javascript
复制
Benchmark            Mode  Cnt   Score   Error  Units
SOExample.bmHashMap  avgt   25  22.059 ± 0.276  ns/op

使用java-9:

代码语言:javascript
复制
Benchmark            Mode  Cnt   Score   Error  Units
SOExample.bmHashMap  avgt   25  23.954 ± 0.383  ns/op

结果几乎没有一个明显的差别(毕竟是纳米秒),正如你看到的。另外,如果您真的想测试HashMap::get,那么您的方法就可以简单地返回该调用,如下所示:

代码语言:javascript
复制
@Benchmark
@Fork(5)
public int bmHashMap(SOExample.Data data) {
    return data.hashmap.get(data.key); // where key is a random generated possible key
}
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46988645

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档