多图空间问题:番石榴

Arp*_*sss 9 java database hashmap guava

在我的Java代码中,我使用的是Guava的Multimap(com.google.common.collect.Multimap):

 Multimap<Integer, Integer> Index = HashMultimap.create()
Run Code Online (Sandbox Code Playgroud)

这里,Multimap键是URL的一部分,值是URL的另一部分(转换为整数).现在,我分配了我的JVM 2560 Mb(2.5 GB)堆空间(通过使用Xmx和Xms).但是,它只能存储9百万这样的(键,值)整数对(大约1000万).但是,理论上(根据占用的内存int)它应该存储更多.

有谁能够帮我,

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

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

Ted*_*opp 11

与之相关的开销很大Multimap.最低限度:

  • 每个键和值都是一个Integer对象,它(至少)使每个int值的存储要求加倍.
  • 其中的每个唯一键值HashMultimap与一个Collection值相关联(根据,Collection是a Hashset).
  • 每个Hashset都使用8个值的默认空间创建.

因此,每个键/值对(至少)要求比两个int值所期望的空间大一个数量级.(当多个值存储在单个密钥下时,会少一些.)我希望1000万个键/值对可能需要400MB.

虽然你有2.5GB的堆空间,但如果这还不够,我也不会感到惊讶.我认为上述估计偏低.此外,它只考虑了构建地图后存储地图所需的数量.随着地图的增长,需要重新分配和重新分配表格,这暂时至少使用的空间量增加一倍.最后,所有这些都假设int值和对象引用需要4个字节.如果JVM使用64位寻址,则字节数可能会翻倍.

  • 写的"HashSet"是一个众所周知的内存hog,只是在内部委托给一个`HashMap`,所有额外的内存开销都有一个附加到每个键的值.基本上我正在进行番石榴内部重写. (2认同)
  • 路易斯,听起来很惊讶,由于对齐,每个条目不必要的"值"字段没有额外的开销.(我已经尝试复制HashMap的代码,删除"value",并创建一个HashSet,并且内存占用量完全相同,以一定数量的单词为模) (2认同)
  • @ eneveu,fyi在下一发行版中,默认值8变为默认值2! (2认同)

Lou*_*man 5

最小化内存开销的最简单方法可能是潜在地混合Trove的原始集合实现(以避免装箱的内存开销)和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());
    }
  });
Run Code Online (Sandbox Code Playgroud)

这仍然具有对查询进行装箱和拆箱的开销,但是仅坐在那里所消耗的内存将大大减少。