计算HashMap的开销在Java中(Calculating HashMap overhead in

2019-09-19 20:07发布

比方说,我存储在一个HashMap 1000个对象。 此HashMap扩展到允许我绘制三维坐标存储在它的对象; 物体内具有固定的大小。 散列键是一个长整型。

我怎么会去搞清楚(数学)可能的开销这种结构?

  1. 它足以显著的是,举例来说,如果里面的数据是256MB左右的开销会事?
  2. 有没有一种可靠的方法(除了一个分析器,其中我发现是不可靠的在某些情况下),数学上计算其开销应该是什么?

我不感兴趣的HashMap的总规模-只有开销 ,使用HashMap的将收取。 举例来说,如果我有10个整数,他们是4个字节的一块,所以它的40个字节。 如果我在阵列中把它们粘,我得到的12个字节的恒定的开销 - 为对对象标头,4为长度8。 如果我把它们放在另一个结构(一个TreeSet比如)我的开销,也不会因为一棵树需要的节点是恒定的 - 所以我可能会得到一个架空的N来表示,其中n是集合的项目数。

有几件事情是很明显对我来说,我会在这里给我的出发点。

  1. 我将需要存储至少1000多头。 这些都是可空类型,所以它们实际上是对象。 我将因此假定正在使用的8字节长的整数的目的头部还8个字节。 我将增加16N的一个因素。
  2. 我需要每一个对象的引用为好,这必须存在与否的对象已经从地图调用和正在使用; 所以这是每个对象的附加的8个字节。 我们可以因素入数据大小,而不是,而是因为引用是HashMap的本身,我觉得这是最让他们开销的一部分。 我的逻辑是:如果我把所有的数据从HashMap中的并将其存储在变量,这n个引用仍然存在于HashMap中,提供我没有删除这些数据对象,我不会做。 对象的集合是恒定的,尽管它们可以用不同的密钥被回收。
  3. HashMap中本身具有的8个字节的开销。
  4. HashMap中必须存储的项目数内(或因此我认为!)所以这就是4个字节。
  5. 我会无知假设哈希键是一个数组,通过哈希键顺序排序。 这对数组12个字节。
  6. 我将无知假设以及该对象是在匹配阵列中,当它找到的关键它解引用。 我会想另一个12个字节。

这给了我一个多项式方程:36 + 24N

因此我有24036个字节的开销用于使用长密钥1000个的数据对象猜测。 这是有些微不足道的开销,但我对你的问题是,什么是真正的开销,只是坐在那里?


二次有效的问题是,要花多少钱这个变化从JVM到JVM? 有没有弄清楚任何JVM独立的方式? 为举例说明我的意思是,考虑JVM仅具有32位对象的头 - 看着数组,你可以说的时候,即使大小从JVM变化到JVM,这是一个合理的估计,一个阵列上的开销将成为8个字节,而不是12在这种情况下。

我假设在同样的Java版本的固定实现的HashMap的。


我可以尝试阅读源代码或运行分析,但是这可能会产生基于JVM我误导性的结果。 我要求你的帮助 - 也许有人谁知道 - 对于某些一块信息,我们都还不知道有关情况。 谢谢!


请参阅下面的答案,实际估计可以表述如下:

每个条目8个字,并为每个长8个字节,加上用于散列映射对象头8个字节。

在我的,使1个字= 4个字节当前环境(32位OS)。

  • 40N + 8在一个32位的环境:〜40K为1000个条目
  • 在64位的环境72N + 8:〜72K为1000个条目。

因此,它似乎是在100kbytes。

Answer 1:

下面的博客文章提供了有关的话题有些松动数学。
此谷歌代码网站提供了一个看这些东西是怎么做的。

引用链路腐烂的情况下,链接:

This is the cheat-sheet I compiled.

To compute the cost of a single (key, value) entry:

    If you use HashMap or ConcurrentHashMap, the cost is 8 words (32 bytes)


 So, consider this example from the javadoc:

   LoadingCache graphs = CacheBuilder.newBuilder()
       .maximumSize(10000)
       .expireAfterWrite(10, TimeUnit.MINUTES)
       .removalListener(MY_LISTENER)
       .build(
           new CacheLoader() {
             public Graph load(Key key) throws AnyException {
               return createExpensiveGraph(key);
             }
           });


The cost of an Entry in this structure this is computed as follows:

    It's a Cache: +12 words
    It uses maximumSize(): +4 words
    It uses expiration: +4 words

Thus, each (key, value) entry would have a footprint of 20 words (thus 80 bytes in a 32bit VM, or 160 in a 64bit one). 

To estimate the overhead imposed in the garbage collector, one could count how many references (pointers) each entry introduces, which the garbage collector would have to traverse to compute object reachability. The same list again, this time only counting references:

    If you use HashMap or ConcurrentHashMap, the cost is 5 references


Answer 2:

创建在其中创建所有对象并将其存储在一个简单的数组的程序。 测量所使用的存储器(参见运行时 )。

然后将它们存储在一个HashMap。 测量使用的内存。

减去第一测量存储器到第二用过的存储器,并且您有HashMap中的开销。



Answer 3:

  1. 它足以显著的是,举例来说,如果里面的数据是256MB左右的开销会事?

当然不。 1000个对象的一个​​HashMap中的开销是不值得担心在任何情况下:如果他们256MB各总,就更少了。 如果塔顶为256K,这实在不行,那只能是1%。 不重要。

  1. 有没有一种可靠的方法(除了一个分析器,其中我发现是不可靠的在某些情况下),数学上计算其开销应该是什么?

鉴于我的回答(1)的问题是没有实际意义。



文章来源: Calculating HashMap overhead in Java