首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

关于dictionary过大,造成内存溢出的解决办法

2012-06-20 
关于dictionary过大,造成内存溢出的解决方法任务背景:海量数据的信息检索.处理数据总规模我们目前大概是20

关于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倍的内存,所以可能包含的数据量不大,但占用的内存却非常多。
------解决方案--------------------


LZ可以一行一行的读数据:
然后insert到DB,insert之前select一下,有就把count字段值+1,没有就insert。
select可以用select top 1,因为每条记录只可能出现一次,找到一个下面就无需再遍历了。
[解决办法]

探讨
类似问题确实前两天问过,分数不够分了,所以另开了一个帖子。
感谢大家的支持,我还是没明白dictionary为什么会占用那么多内存。呵呵。
为什么这么说呢?比如:我实验观察,将其保存到硬盘上是300M时,其占用内存达到1G左右。郁闷阿。
有的朋友说用lucence,我的经验是,他根本处理不了这么大数据,也就能玩个百八十个G撑死了。(06年的经验,新版本不清楚。呵呵)。
用数据库利用它的排序统计之类的肯定可以实现,不过,这么大的数据塞给数据库,第一,我需要再弄相同大小的硬盘,倒入,然后group by之类的,数据库我尝试过1G的,已经有点慢了。
至于还有位朋友说的,每个单词一个文件名,实现起来很简单,但唯一的缺点是,现有的操作系统目录下的文件如果过大的话,访问起来是一件很可怕的事情。呵呵。比如大家在一个文件夹下放上100W个文件,嘿嘿,哪怕是1k的,打开这个文件夹试试,就知道有多爽了。


我将文件分成10G一份,一个文件一个文件处理,然后倒入到数据库嘿嘿group by 一下,这样占用的很少,又利用的数据库的外排序统计功能,不过,毕竟还要操作好几步,不太爽阿。谁还有建议,大家再议议。

[解决办法]
省内存的话可以考虑SortedList,查的时候绝对比Dictionary快,可是删除或者增加就不是很理想了
[解决办法]
把上边的方法综合一下,不要一次一更新,攒个1000-2000个记录到数据库更新一下

比如,DIC里面有了1000条记录,就序列化成XML到数据库里更新一下,然后清空DIC
等下次满了1000再更新一下

1000只是预计值,我估计如果允许,能几千更新一次


数据量在这摆着,再好的办法也能用不少时间
[解决办法]
探讨
引用:
把上边的方法综合一下,不要一次一更新,攒个1000-2000个记录到数据库更新一下

比如,DIC里面有了1000条记录,就序列化成XML到数据库里更新一下,然后清空DIC
等下次满了1000再更新一下

1000只是预计值,我估计如果允许,能几千更新一次


数据量在这摆着,再好的办法也能用不少时间


海量数据是真的,不过其实出现的词并不多,存下来估计也就2个G左右(这个我可以考虑用64位系统,8G内存搞定),问题是现在实验阶段一个文件,单词数2千多万,存储到硬盘上才300M,占用的内存就能达到2G,这是为什么呢?

[解决办法]
这种任务是一次性的还是每周都要做一下,总得给个情况吧,20T什么之类的都不是什么问题,关键是你时间上的安排。人家有些解密算法光运算都要几个月呢
[解决办法]
探讨
Dictionary初始的时候是按Capacity占用内存的,当达到上限则会增长到至少2倍的内存,所以可能包含的数据量不大,但占用的内存却非常多。

热点排行