首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Java计算HashMap开销

用Java计算HashMap开销
EN

Stack Overflow用户
提问于 2012-07-19 16:48:02
回答 3查看 6.8K关注 0票数 4

假设我在hashmap中存储了1000个对象。这个hashmap被扩展为允许我将三维坐标映射到存储在其中的对象;里面的对象有一个固定的大小。散列键是一个长整数。

我将如何(从数学上)计算出这个结构的可能开销?

  1. 例如,如果内部的数据大约为256 it,那么开销是否足够重要?
  2. 是否有可靠的方法(除了我发现在某些情况下不可靠的分析器之外),从数学上计算它的开销应该是多少?

我对hashmap的总大小不感兴趣--只关心使用hashmap将带来的开销。例如,如果我有10个it,它们是4个字节,所以是40个字节。如果将它们放入数组中,则会得到12字节的恒定开销--对象头为8,长度为4。如果我将它们放在另一个结构中(例如,一个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

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

另一个有效的问题是,JVM和JVM之间的差别有多大?有什么JVM独立的方法可以解决这个问题吗?为了举例说明我的意思,请考虑一个只有32位对象头的JVM --当查看数组时,您可能会说,尽管JVM的大小各不相同,但公平地估计,数组上的开销将成为8字节,而不是12字节。

我假设在同一个版本的HashMap上有一个固定的实现。

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

见下文的答复,实际估计数可表示如下:

每个条目8个字,每个长加上8个字节,加上hashmap对象头的8个字节。

在我目前的环境(32位OS)中,1字=4字节。

  • 32位环境中的40n +8: 1000项~ 40k
  • 在64位环境中,72n +8: 1000项~ 72k。

所以它似乎在100千字节以下。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-07-19 17:22:04

下面的博客帖子提供了关于这个主题的一些松散的数学。

这个谷歌代码站点介绍了这些事情是如何完成的。

在链接腐烂的情况下引用链接:

代码语言:javascript
复制
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
票数 3
EN

Stack Overflow用户

发布于 2012-07-19 17:00:33

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

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

将第一个测量的内存减去第二个使用的内存,您就有了HashMap的开销。

票数 0
EN

Stack Overflow用户

发布于 2012-07-20 10:09:09

  1. 例如,如果内部的数据大约为256 it,那么开销是否足够重要?

绝对不是那么回事。HashMap中的1000个对象的开销在任何情况下都不值得担心:如果每个对象的总容量为256‘t,那么就更不必担心了。如果管理费用是256 K,而事实并非如此,那就只有1%了。没什么意义。

  1. 除了我在某些情况下发现的不可靠的分析器之外,是否有一种可靠的方法来计算它的开销呢?

鉴于我对(1)的回答,这个问题是毫无意义的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11565554

复制
相关文章

相似问题

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