java - Guava ImmutableMap 的访问速度明显比 HashMap 慢

标签 java performance hashmap benchmarking guava

在对一些高吞吐量数据结构进行内存基准测试时,我意识到我可以使用 ImmutableMap 只需进行一点重构。

认为这将是一个改进,我将其投入其中,并惊讶地发现它不仅比 HashMap 慢,而且在单线程环境中它似乎一直更慢,甚至比 ConcurrentHashMap!

你可以看到full benchmark

测试的内容非常简单,计算获取 map 中可能存在的大量随机字符串需要多长时间。

public static void timeAccess(Map<String,String> map) {
    Random rnd = new Random(seed);
    int foundCount = 0;

    long start = System.nanoTime();

    for(int i = 0; i < loop; i++) {
        String s = map.get(RndString.build(rnd));
        if(s != null)
            foundCount++;
    }

    long stop = System.nanoTime() - start;

    System.out.println("Found "+foundCount+" strings out of "+loop+" attempts - "+
        String.format("%.2f",100.0*foundCount/loop)+" success rate.");
    System.out.println(map.getClass().getSimpleName()+" took "+
        String.format("%.4f", stop/1_000_000_000.0)+" seconds.");
    System.out.println();
}

并且针对包含相同值的 HashMapConcurrentHashMapImmutableMap 运行此程序,当使用 ImmutableMap - 通常会慢 15% 以上。 map 越稀疏(即 map.get() 返回 null 的频率越高)差异越大。这是示例运行的结果:

Found 35312152 strings out of 100000000 attempts - 35.31 success rate.
HashMap took 29.4538 seconds.

Found 35312152 strings out of 100000000 attempts - 35.31 success rate.
ConcurrentHashMap took 32.1465 seconds.

Found 35312152 strings out of 100000000 attempts - 35.31 success rate.
RegularImmutableMap took 37.9709 seconds.

这是记录/预期的问题吗? Guava Docs表示 Immutable*** 内存效率更高,但没有说明速度。对于这种程度的减速,我倾向于处理内存成本并在速度成为问题时避免使用 Immutable*** (什么时候不是?!)。我错过了什么吗?

另请参阅:https://groups.google.com/forum/?fromgroups=#!topic/guava-discuss/I7yPpa5Hlpg

最佳答案

正如 Louis Wasserman 所说,ImmutableMap 没有针对具有慢速 equals 方法的对象进行优化。我认为主要区别在这里:

HashMap :

if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
    return e.value;

ImmtubleMap :

if (key.equals(candidateKey)) {
    return entry.getValue();

如您所见,要检查冲突,HashMap 首先检查哈希。这允许快速拒绝具有不同哈希值的值。由于 String 不会在其 equals 方法中进行此检查,因此这会使 HashMap 更快。 ImmutableMap 不使用此优化,因为当 equals 已经优化时,它会使测试变慢。

关于java - Guava ImmutableMap 的访问速度明显比 HashMap 慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15756940/

相关文章:

java - 不断收到错误消息“找不到符号 - 构造函数帐户(int,double)

JavaBean setter方法调用错误 "wrong number of arguments"

java - 如何从子类访问主类的公共(public)常量变量?

javascript - 我应该将 jQuery 或 DOM 对象作为参数传递吗? (性能问题)

Android: map 绘制性能,1K图纸!

java - Json 字符串到 map 的转换,

java - 这是否违反单一责任原则?

java - Java中推荐使用ArrayList和HashMap?

java - 你能帮我合并几个 map 的值吗?

java - 关于Java中选择合适的数据结构的问题