在我的Java代码中,我使用的是Guava的Multimap(com.google.common.collect.Multimap):
Multimap<Integer, Integer> Index = HashMultimap.create()
这里,Multimap键是URL的一部分,值是URL的另一部分(转换为整数)。现在,我分配了我的JVM 2560 Mb(2.5 GB)堆空间(通过使用Xmx和Xms)。但是,它只能存储9百万这样的(键,值)整数对(大约1000万)。但是,理论上(根据int
占用的内存)它应该存储更多。
任何人都可以帮助我,
Multimap
使用大量内存?我检查了我的代码而没有插入Multimap
对,它只使用了1/2 MB的内存。是否有另一种解决此内存问题的方法或主场解决方案?意味着,有没有办法减少这些对象开销,因为我只想存储int-int?用其他语言?或者解决我遇到的问题的任何其他解决方案(自制首选),意味着基于数据库或类似解决方案。
答案 0 :(得分:9)
与Multimap
相关的开销很大。至少:
Integer
对象,它(至少)会使每个int
值的存储要求加倍。HashMultimap
中的每个唯一键值都与Collection
个值相关联(根据the source,Collection
是Hashset
)。< / LI>
Hashset
。因此,每个键/值对(至少)可能比两个int
值所需的空间大一个数量级。 (当多个值存储在单个密钥下时,会少一些。)我预计1000万个键/值对可能需要400MB。
虽然你有2.5GB的堆空间,如果这还不够,我不会感到惊讶。我认为上述估计偏低。此外,它只考虑了构建地图后存储地图所需的数量。随着地图的增长,需要重新分配和重新分配表格,这暂时至少使用的空间量增加一倍。最后,所有这些都假定int
值和对象引用需要4个字节。如果JVM使用64位寻址,则字节数可能会翻倍。
答案 1 :(得分:4)
最小化内存开销的最简单方法可能是混合Trove's原始集合实现(以避免装箱的内存开销)和Guava的Multimap
,类似
SetMultimap<Integer, Integer> multimap = Multimaps.newSetMultimap(
TDecorators.wrap(TIntObjectHashMap<Collection<Integer>>()),
new Supplier<Set<Integer>>() {
public Set<Integer> get() {
return TDecorators.wrap(new TIntHashSet());
}
});
在查询中仍然存在装箱和拆箱的开销,但它只是坐在那里消耗的内存会大大减少。
答案 2 :(得分:1)
听起来你需要一个稀疏的布尔矩阵。 Sparse matrices / arrays in Java应该提供指向库代码的指针。然后,不要将(i,j)放入多图,只需将1放入[i] [j]的矩阵中。
答案 3 :(得分:0)
你可能使用一个ArrayListMultimap,它需要比HashMultimap更少的内存,因为ArrayLists小于HashSets。或者,您可以修改路易斯的Trove解决方案,将Set替换为List,以进一步减少内存使用量。
某些应用程序依赖于HashMultimap满足SetMultimap接口这一事实,但大多数都没有。