C#无法清除大型通用集合的内存

Gra*_*ant 4 c# generics collections garbage-collection

我将2个非常大的数据集放入内存,执行连接以从第一个集合中过滤出一个子集,然后尝试销毁第二个集合,因为它使用了大约600MB的系统RAM.问题是下面的代码不起作用.在下面的代码运行后,foreach循环运行大约需要15分钟.在此期间,内存不会从600MB +减少.难道我做错了什么?

List<APPLES> tmpApples = dataContext.Apples.ToList(); // 100MB
List<ORANGES> tmpOranges = dataContext.Oranges.ToList(); // 600MB

List<APPLES> filteredApples = tmpApples
    .Join(tmpOranges, apples => apples.Id, oranges => oranges.Id, (apples, oranges) => apples).ToList();
tmpOranges.Clear();
tmpOranges = null;
GC.Collect();
Run Code Online (Sandbox Code Playgroud)

注意我以后重新使用tmpApples所以我现在不清除它..

Ste*_*ven 5

清除,取消和收集几乎没有任何(积极的)效果.GC将自动检测何时不再引用对象.更进一步,只要Join操作运行,无论是tmpApplestmpOranges集合引用,并用它所有的对象.因此无法收集它们.

更好的解决方案是在数据库中执行过滤:

// NOTE That I removed the ToList operations
IQueryable<APPLE> tmpApples = dataContext.Apples;
IQueryable<ORANGE> tmpOranges = dataContext.Oranges;

List<APPLES> filteredApples = tmpApples
    .Join(tmpOranges, apples => apples.Id, 
       oranges => oranges.Id, (apples, oranges) => apples)
    .ToList();
Run Code Online (Sandbox Code Playgroud)


Jon*_*eet 5

有几点需要注意:

  • 除非您dataContext可以清除/垃圾收集,否则很可能会保留对很多对象的引用
  • Clear()如果你真的没有对列表做任何其他事情,那么调用然后将变量设置为null是没有意义的.几乎在所有情况下,GC都可以判断您何时不再使用变量.
  • 据推测,你正在判断这个过程保留了多少内存; 我不认为CLR实际上会将内存返回给操作系统,但是已经被垃圾收集释放的内存可以 CLR中进一步使用.(编辑:根据下面的评论,CLR可能释放大对象堆的区域,但我不确定.)