日期:2014-05-18  浏览次数:21871 次

关于dictionary过大,造成内存溢出的解决方法
任务背景:海量数据的信息检索.处理数据总规模我们目前大概是20T,需要对这20T数据进行索引,然后构造一个简易的检索系统.
现在的问题:
假设有一个大文件1T左右,里面每一行是一个单词,任务很简单,统计一下,每个单词出现了多少次,存储下来。 

  我现在的实现大概是这样的 
  
  Dictionary <string,int> a=new Dictionary <string,int>(); 
   
  while 循环读入 word 
  { 
  object b; 
  b=a[word]; 
  if (b==null) 
  a.add(word) 
  else 
  a[word]++; 
  } 
在处理了大概20G左右数据以后,内存溢出了。 

{"引发类型为“System.OutOfMemoryException”的异常。"} 
{System.Collections.ListDictionaryInternal} 
{System.Collections.ListDictionaryInternal.NodeKeyValueCollection} 


{Void Resize()} 
System.Reflection.MethodAttributes.Private 
|System.Reflection.MethodAttributes.HideBySig 

分析应该是dictionary在冲突发生比较大的时候进行扩容,此时可用内存耗光或者超过了2G的限制。 
我现在的疑问是
问题1: 2千多万个词,实际上存储的话要几十M就应该够了,为什么我发现占用的内存会很高(占用物理内存就1.5G)呢?远远要超出预估算的值,各位可以简单写个代码往里面存点数据就会发现其实是非常消耗内存的?why?
问题2:如果确实超过内存,那么这项工作该如何实现呢?

------解决方案--------------------
确定是英文单词么?把不是单词的打出来看看(用wordnet)?会不会有很多?

这个应用用hadoop wordcount例子的好合适
------解决方案--------------------
这种索引用lucene做也很容易
------解决方案--------------------
简单,吧在dictionary里存放的东西都放在一个文本文件里
------解决方案--------------------
1.hash表本来就是耗内存的数据结构;文件大小1T,内存2G,就算用数组在较差的情况下也会内存不足
2.可以导入数据库,由数据库决定如果处理;如果一定要写程序解决,可能要用外排序才能解决问题
------解决方案--------------------
别一次读进来啊
先读1000行,按单词分组 -> 统计行数 ->存储结果
再读1000行 如此循环。。
我写个试试看

------解决方案--------------------
帮顶一下!!
------解决方案--------------------
按照平均单词长度8位来算的话100w单词占用内存50m,假如单词再长一些2000w占用1.5g也算是合理的..
即使是自己实现dictionary也省不了多少内存,剩下的只能一次少读点了...

如果不要求速度的话也可以分几次做,每次只处理几个字母开头的单词,中间gc.collect一下,然后再处理其他的,最后把结果合并起来
------解决方案--------------------
我记得Dictionary是有大小限制的,忘了上限是多少了
像你这种情况,可以试试这样

Dictionary <string, Dictionary <string,int>>
将你要处理的内容,合理的处理一下,放到这里面 就不存在溢出问题了
------解决方案--------------------
我有个思路:
1. 新建一个Folder,比如Result
2. 你就不要用Dict了,直接用txt文件来存储
3. Dictionary <string, int>, string对应文件名,int对应txt文件内容
4. 这样你拿到一个string直接可以用文件路径去查找,有这个文件就把其txt内容取出+1,没有这个文件,就新建,内容为1

LZ你懂我的意思吧?

------解决方案--------------------
用lucene吧,数据量太大Dictionary吃不消,耗内存的问题嘛,我之前也测试过,如果Key是字符串,而且比较长的话,吃内存较厉害,如果是int效果好些
------解决方案--------------------
直接用数据库来统计不是很容易吗?永远不存在内存问题.
------解决方案--------------------
我估计LZ那些数据不是在数据库里的,导入一次数据库估计要很久很久。。。
------解决方案--------------------
用数据库来统计,
建个表就是了
------解决方案--------------------
有意思,非实践的人不会遇到
------解决方案--------------------
直接用数据库来统计 试试
------解决方案--------------------
Dictionary初始的时候是按Capacity占用内存的,当达到上限则会增长到至少2倍的内存,所以可能包含的数据量不大,但占用的内存却非常多。
------解决方案--------------------