回答
如果在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美分。
我真的不明白这个问题的前提 - 要么你需要并发性,要么你不需要。
但是,根据this link,空的ConcurrentHashMap
的存储器占用空间为1700字节。如果您有多个需要读取/写入权限的线程,它建议您使用ConcurrentHashMap
,如果您有多个需要读取权限的线程,而有一个需要读取权限,则建议您使用ConcurrentHashMap
。
ConcurrentHashMap
在构建和插入时不会使用比HashMap
更多的内存。
在Intialization
ConcurrentHashMap
使用几乎相同的内存量是一个HashMap,可能会稍微多为对额外的簿记变量和锁。
在初始化过程中,ConcurrentHashMap
创建16个段来存储键值,每个段相当于一个HashMap。
每个部分的初始容量/大小是整个初始容量的1/16。所以实质上,ConcurrentHashMap
创建了16个相当于一个HashMap的小型HashMap。每个段都有自己的锁和一些记账变量(计数,阈值等),这是额外的内存开销。
通过将适当的值传递给concurrencyLevel参数到ConcurrentHashMap
,您可以控制由ConcurrentHashMap
创建的分段数。这个值越小,那么当更多的线程更新映射时,将会使用更少的空间,但更多的争用。此值越高,则会创建更多细分,但并行更新的性能会更快。注意:参数concurrencyLevel的值显着较高,同时影响空间和时间。
内存中的这个小开销是开发人员为了交换并发而愿意接受的。
在插入
在分类得到填补,该片段的大小将增加。增加大小的策略与HashMap相同。 负载因子参数决定何时增加段的大小。请注意,填充的细分将会增加。内存开销再次与HashMap几乎相同。
总体而言,ConcurrentHashMap
不会使用比HashMap
更多的内存,但它很难测量ConcurrentHashMap
使用的每个额外字节。
- 1. ConcurrentHashMap内存分配
- 2. CoreData内存开销
- 3. neo4j的内存开销
- 4. SQL游标内存开销
- 5. Grails的内存泄漏 - ConcurrentHashMap的
- 6. 每个节点的内存开销
- 7. EclipseLink JAXB和JPA内存开销
- 8. 列表<object>内存开销
- 9. 英特尔tbb内存开销
- 10. Lucene Sort增加内存开销
- 11. 超过jmeter的gc内存开销
- 12. 使用DictReader节省内存开销
- 13. 内存传输开销往来Intel MIC
- 14. 内存屏障/栅栏的开销
- 15. 哈希映射内存开销
- 16. HDF5存储开销
- 17. 在.NET DataTable中存储数据的内存开销是多少?
- 18. Riak内存中存储每个密钥的开销
- 19. Android:onBackPressed()销毁所有内存?
- 20. fbconnect注销内存泄漏
- 21. 哈希集内存开销如何取决于对象大小?
- 22. (Javascript)空数组的内存开销vs未定义的var?
- 23. 无需内存开销设置Eigen :: SparseMatrix的稀疏模式
- 24. 内存不足错误 - 超出GC开销限制
- 25. 虚拟内存如何增加上下文切换开销?
- 26. GC堆大小和程序内存开销
- 27. java的import语句的开销内存或JVM
- 28. 用ifort编译的openmp程序690mb内存开销
- 29. JDOM需要多少“开销”内存来生成XML文件?
- 30. Java 32位和64位优化模式(-XX:-UseCompressedOops)内存开销
创建大量的ConcurrentHashMap让你只有有限数量的内核是没有意义的。少量CHM的开销可能低于1美分内存。 –
@PeterLawrey我真的不明白你的观点。 “创建大量的ConcurrentHashMap是无用的”,那又如何?他们仍然有开销。除此之外,即使在同时拥有很多CHM的情况下显然很奇怪,人们可以很容易想象,短生命对象在其构建时创建了一个并发哈希映射(让我们来说一个面向数据库的软件中的连接运算符?)。 – Maxime
您可能会使用并发集合的原因是因为您拥有的核心多于集合。如果你拥有比核心更多的集合,那么你不太可能拥有并发访问权限。 –