有人知道ConcurrentHashMap的内存开销是什么(与“经典”HashMap相比)?
答案 0 :(得分:8)
如果在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获得一百万个条目。
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美分。
答案 1 :(得分:4)
ConcurrentHashMap
在构造和插入时都没有使用比HashMap
更多的内存。
初始化
ConcurrentHashMap
使用与HashMap几乎相同的内存量,对于一些额外的簿记变量和锁可能稍微多一些。
在初始化期间,ConcurrentHashMap
创建16个段来存储键值,每个段相当于一个HashMap。
每个细分的初始容量/大小是整个初始容量的1/16。所以实质上,ConcurrentHashMap
创建了16个小HashMaps,相当于一个HashMap。每个Segment都有自己的锁和几个簿记变量(计数,阈值等),这是额外的内存开销。
您可以通过将适当的值传递给 concurrencyLevel 参数来ConcurrentHashMap
来控制ConcurrentHashMap
创建的细分数量。这个值越小,那么将使用更少的空间,但是当大量线程更新Map时会有更多争用。该值越高,则将创建更多段,但并行更新的性能将更快。注意: concurrencyLevel 参数的值显着更高,会影响空间和时间。
内存中的这种小开销是开发人员愿意接受以换取并发性的内容。
在插入
当细分填充时,该细分的大小将会增加。增加大小的策略与HashMap相同。 loadfactor 参数决定何时增加Segment的大小。请注意,填充的段将增加。内存开销再次与HashMap几乎相同。
总体而言,ConcurrentHashMap
并未使用比HashMap
更多的内存,但实际上很难衡量ConcurrentHashMap
使用的每个额外字节。
答案 2 :(得分:2)
我真的不明白这个问题的前提 - 要么你需要并发,要么你不需要。
但是,根据this link,空ConcurrentHashMap
的内存占用量为1700字节。如果您有多个需要读/写访问权限的线程,建议您使用ConcurrentHashMap
,如果您有许多线程需要读取权限但是有一个需要写入,则建议使用Hashtable
。