Max*_*ime 10 java hashmap concurrenthashmap memory-profiling
有人知道ConcurrentHashMap的内存开销是什么(与"经典"HashMap相比)?
如果-XX:-UseTLAB -XX:NewSize=900m -mx1g在64位JVM上运行以下命令.
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();
}
Run Code Online (Sandbox Code Playgroud)
你可以使用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.
Run Code Online (Sandbox Code Playgroud)
8 MB的内存成本约为5美分.
ConcurrentHashMapHashMap在构造和插入时,不会使用比 多得多的内存。
初始化时
ConcurrentHashMap使用与 HashMap 几乎相同的内存量,对于几个额外的簿记变量和锁可能会稍微多一些。
初始化时,ConcurrentHashMap创建16个Segment来存储key-value,每个Segment相当于一个HashMap。
每个Segment的初始容量/大小是总体初始容量的1/16。所以本质上,ConcurrentHashMap创建了16个小HashMap相当于1个HashMap。每个段都有自己的锁和几个簿记变量(计数、阈值等),这是额外的内存开销。
ConcurrentHashMap您可以通过将适当的值传递给concurrencyLevel参数来控制创建的 Segment 数量ConcurrentHashMap。该值越小,则使用的空间越少,但当大量线程更新 Map 时,争用会更多。该值越高,将创建更多的段,但并行更新的性能会更快。注意: concurrencyLevel参数的值明显较高,会影响空间和时间。
这种小的内存开销是开发人员愿意接受的,以换取并发性。
插入时
当段被填满时,该段的大小将增加。增加大小的策略与HashMap相同。loadfactor参数决定何时增加 Segment 的大小。请注意,填充的段将会增加。再次强调,内存开销与 HashMap 几乎相同。
总体而言,ConcurrentHashMap使用的内存并不比 多得多HashMap,但确实很难测量 所使用的每个额外字节ConcurrentHashMap。