【问题标题】:Calculating memory requirements for HashMap in Java在 Java 中计算 HashMap 的内存需求
【发布时间】:2021-01-08 16:31:19
【问题描述】:

我有一个像这样的 ConcurrentHashMap:

HashMap<String, Integer> fruitMap = new ConcurrentHashMap<>();

键是 10 个字符的 String,值是 Integer

假设我的应用程序中没有其他消耗内存的代码,我如何计算可以存储在 10GiB 内存服务器上的 HashMap 中的条目数?

如果您能提及我们如何为 Java 7 和 Java 8 或更高版本计算它,那就太好了。

PS:我找到了this,但我不明白 100 个 int 映射到 int 的 hashmap 的 6.75KB 内存使用量是如何得出的。

【问题讨论】:

  • 这取决于 JVM 版本、堆的大小以及某些启用/禁用标志。没有X 答案。当然HashMap 不能分配给ConcurrentHashMap
  • 你不会得到一个确切的数字,但是一个大概的数字,对你来说足够了吗,例如10M 条目 vs. 100m 整体 vs. 1B 条目!?
  • 6.75KB 是因为,它不是存储的原始类型,而是具有一些开销的 Integer 对象。参考这个-stackoverflow.com/questions/8419860/…。此外,哈希映射在内部将数据存储在桶中......映射到相同哈希码的所有键都将在同一个桶中。这也有一些开销。
  • @luk2302 为什么这么说?当然,您可以在启用特定标志的特定 JVM 版本下计算确切的大小。
  • @Eugene 确切的大小将取决于确切的内容(对桶、链等的影响)、负载因子、并发级别、初始大小等,因此很难一概而论。

标签: java memory hashmap


【解决方案1】:

我将只为您提供一个使用JOL(这是我所信任的唯一可靠工具)针对jdk-15 的示例,对于具有10 个条目的ConcurrentHashMap,这取决于您。

Map<String, Integer> throttleMap = new ConcurrentHashMap<>();

for(int i = 0; i< 10; ++i){
    throttleMap.put((""+i).repeat(10), i);
}

System.out.println( GraphLayout.parseInstance((Object)throttleMap).toFootprint());

这将输出:

 COUNT       AVG       SUM   DESCRIPTION
    10        32       320   [B
     1        80        80   [Ljava.util.concurrent.ConcurrentHashMap$Node;
    10        16       160   java.lang.Integer
    10        24       240   java.lang.String
     1        64        64   java.util.concurrent.ConcurrentHashMap
    10        32       320   java.util.concurrent.ConcurrentHashMap$Node
    42                1184   (total)

了解以上内容并非易事。 Integer 是最简单的:

  • 12 个字节用于两个标头
  • 4 个字节用于内部 int 字段

所以16 bytes 一个,你有 10 个,因此那一行:

0        16       160   java.lang.Integer

String 的实例更复杂:

  • 12 字节的标头
  • hash 字段为 4 个字节
  • coder 字段为 1 个字节
  • hashIsZero 字段 (what is hashIsZero?) 的 1 个布尔值
  • 2 字节用于填充
  • value (byte []) 为 4 个字节

所以24 bytes * 10:

 10        24       240   java.lang.String

那个内byte []也会加:

  • 12 字节的标头(byte[] 是一个对象)。
  • length 字段为 4 个字节
  • 10 个字节,每个字节 10 个字节
  • 6 字节填充

因此:

 10        32       320   [B

了解整体情况留给您作为练习。

【讨论】:

  • 输出中的其他行表示什么? 10 32 320 [B1 80 80 [Ljava.util.concurrent.ConcurrentHashMap$Node1 64 64 java.util.concurrent.ConcurrentHashMap最后的输出行是不是表示总共使用了1184字节?:42 1184 (total)
  • @seeker 是的,这意味着 1184 字节。
  • 谢谢。我仍然想知道输出中的第 1 行和输出中的第 6 行有什么区别。为什么320 bytes被使用了两次?
  • @seeker 不同的对象,正如Description 字段所说的那样?
  • 对。我试图了解[B (bytes[]) 用于什么以及java.util.concurrent.ConcurrentHashMap$Node 用于什么?其中一个大概是用来存储HashMap的bucket信息,但是到底是哪一个,另一个是干什么用的。
猜你喜欢
  • 1970-01-01
  • 2011-09-03
  • 1970-01-01
  • 2012-07-18
  • 1970-01-01
  • 2016-05-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多