2012-06-19 30 views
10

有人知道ConcurrentHashMap的内存开销是多少(与“经典”HashMap相比)?ConcurrentHashMap内存开销

  • 在施工?
  • 插入元素?
+0

创建大量的ConcurrentHashMap让你只有有限数量的内核是没有意义的。少量CHM的开销可能低于1美分内存。 –

+0

@PeterLawrey我真的不明白你的观点。 “创建大量的ConcurrentHashMap是无用的”,那又如何?他们仍然有开销。除此之外,即使在同时拥有很多CHM的情况下显然很奇怪,人们可以很容易想象,短生命对象在其构建时创建了一个并发哈希映射(让我们来说一个面向数据库的软件中的连接运算符?)。 – Maxime

+0

您可能会使用并发集合的原因是因为您拥有的核心多于集合。如果你拥有比核心更多的集合,那么你不太可能拥有并发访问权限。 –

回答

6

如果在64位JVM上使用-XX:-UseTLAB -XX:NewSize=900m -mx1g执行以下操作。

public static void main(String... args) throws NoSuchMethodException, IllegalAccessException { 
    for (int i = 0; i < 4; i++) { 
     long used1 = usedMemory(); 
     populate(new HashMap()); 
     long used2 = usedMemory(); 
     populate(new ConcurrentHashMap()); 
     long used3 = usedMemory(); 
     System.out.println("The ratio of used memory is " + (double) (used3 - used2)/(used2 - used1)); 
     System.out.println("For an extra " + ((used3 - used2) - (used2 - used1))/1000000 + " bytes per entry was used."); 
    } 
} 

private static void populate(Map map) { 
    for (Integer i = 0; i < 1000000; i++) 
     map.put(i, i); 
} 

private static long usedMemory() { 
    return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); 
} 

你用Java 6和7获得了100万个条目。

The ratio of used memory is 1.1291128466982379 
For an extra 8 bytes per entry was used. 
The ratio of used memory is 1.1292086928728067 
For an extra 8 bytes per entry was used. 
The ratio of used memory is 1.1292086928728067 
For an extra 8 bytes per entry was used. 
The ratio of used memory is 1.1292086928728067 
For an extra 8 bytes per entry was used. 

8 MB的内存成本大约5美分。

+0

测量内存使用情况的可靠程度如何? – assylias

+0

你能解释一下使用线程本地分配的要点吗?谢谢! – assylias

+0

对于Java 5或其他JVM,它可能与HotSpot或OpenJDK不同,但如果它明显不同,我会感到惊讶。 32位JVM上的差异可能较小。 –

2

我真的不明白这个问题的前提 - 要么你需要并发性,要么你不需要。

但是,根据this link,空的ConcurrentHashMap的存储器占用空间为1700字节。如果您有多个需要读取/写入权限的线程,它建议您使用ConcurrentHashMap,如果您有多个需要读取权限的线程,而有一个需要读取权限,则建议您使用ConcurrentHashMap

+0

链接过于老旧,无法相关。事实上,这篇文章在Java 7之前发布(2012年4月28日),实现可能已经改变。此外,你的回答也是不完整的,因为我也要求插入(有一个)。 – Maxime

+2

@Maxime实现可能没有太大改变,但无论如何它都描述了他们用来查找数据的方法。一些研究表明,还没有其他人做到这一点。 – purtip31

4

ConcurrentHashMap在构建和插入时不会使用比HashMap更多的内存。

在Intialization

ConcurrentHashMap使用几乎相同的内存量是一个HashMap,可能会稍微多为对额外的簿记变量和锁。

在初始化过程中,ConcurrentHashMap创建16个段来存储键值,每个段相当于一个HashMap。

每个部分的初始容量/大小是整个初始容量的1/16。所以实质上,ConcurrentHashMap创建了16个相当于一个HashMap的小型HashMap。每个段都有自己的锁和一些记账变量(计数,阈值等),这是额外的内存开销。

通过将适当的值传递给concurrencyLevel参数到ConcurrentHashMap,您可以控制由ConcurrentHashMap创建的分段数。这个值越小,那么当更多的线程更新映射时,将会使用更少的空间,但更多的争用。此值越高,则会创建更多细分,但并行更新的性能会更快。注意:参数concurrencyLevel的值显着较高,同时影响空间和时间。

内存中的这个小开销是开发人员为了交换并发而愿意接受的。

在插入

在分类得到填补,该片段的大小将增加。增加大小的策略与HashMap相同。 负载因子参数决定何时增加段的大小。请注意,填充的细分将会增加。内存开销再次与HashMap几乎相同。

总体而言,ConcurrentHashMap不会使用比HashMap更多的内存,但它很难测量ConcurrentHashMap使用的每个额外字节。