多图空间问题:番石榴

时间:2012-03-29 17:26:13

标签: java database hashmap guava

在我的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占用的内存)它应该存储更多。

任何人都可以帮助我,

  1. 为什么Multimap使用大量内存?我检查了我的代码而没有插入Multimap对,它只使用了1/2 MB的内存。
  2.  2。

    是否有另一种解决此内存问题的方法或主场解决方案?意味着,有没有办法减少这些对象开销,因为我只想存储int-int?用其他语言?或者解决我遇到的问题的任何其他解决方案(自制首选),意味着基于数据库或类似解决方案。

4 个答案:

答案 0 :(得分:9)

Multimap相关的开销很大。至少:

  • 每个键和值都是Integer对象,它(至少)会使每个int值的存储要求加倍。
  • HashMultimap中的每个唯一键值都与Collection个值相关联(根据the sourceCollectionHashset)。< / LI>
  • 使用8个值的默认空间创建每个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接口这一事实,但大多数都没有。