2012-01-02 3 views
1

실험을 위해 BlockingCollection을 사용하여 프로듀서/소비자 패턴을 구현했습니다. 실행 후GC가 사용하지 않는 개체를 수집하지 않는 이유는 무엇입니까?

PerformanceCounter c = null; 
void Main() 
{ 
    var p =System.Diagnostics.Process.GetCurrentProcess(); 
    c = new PerformanceCounter("Process", "Working Set - Private", p.ProcessName); 

    (c.RawValue/1024).Dump("start"); 
    var blocking = new BlockingCollection<Hede>(); 
    var t = Task.Factory.StartNew(()=>{ 
     for (int i = 0; i < 10000; i++) 
     { 
      blocking.Add(new Hede{ 
      Field = string.Join("",Enumerable.Range(0,100).Select (e => Path.GetRandomFileName())) 
      }); 
     } 
     blocking.CompleteAdding(); 
    }); 

    var t2 = Task.Factory.StartNew(()=>{ 
     int x=0; 
     foreach (var element in blocking.GetConsumingEnumerable()) 
     { 
      if(x % 1000==0) 
      { 
       (c.RawValue/1024).Dump("now"); 
      } 
      x+=1; 
     } 
    }); 
    t.Wait(); 
    t2.Wait(); 
    (c.RawValue/1024).Dump("end"); 
} 

내 메모리 덤프 :

start 
211908 
now 
211972 
now 
212208 
now 
212280 
now 
212596 
now 
212736 
now 
212712 
now 
212856 
now 
212840 
now 
212976 
now 
213036 
end 
213172 

내 메모리를 소모하기 전에 21만1천9백8킬로바이트를이지만, 다른 스레드에서 생산하면서 하나씩 증가했다.

GC는 메모리에서 생성 된 객체를 수집하지 않습니다. 생산자/소비자 패턴을 구현했지만 왜 내 기억력이 증가 했습니까?

+0

통화를 삭제하거나 사용하는 것이 표시되지 않습니다. 컬렉션에 항목을 추가하고 절대로 제거하지 않는 것을 보았습니다. 나는 그 문제가 무엇인지, 또는 당신이 성취하려는 것을 이해하지 못합니다. – Origin

+1

나는 당신이 무엇을 기대하고 있는지 정말로 이해하지 못합니까? – Tudor

+1

출처 : 생산자/소비자 패턴이므로 목록에서 항목을 제거 할 필요가 없습니다. GetConsumingEnumerable()이 (가) 나를 위해 항목을 제거합니다. – oguzh4n

답변

6

기본적으로 BlockingCollection<T>contains a memory leak in .Net 4.0으로 사용되는 ConcurrentQueue<T>입니다. 나는 이것이 당신이 관찰하고있는 문제인지는 모르겠지만 그것이 될 수 있습니다.

곧 출시 될 .Net 4.5에서 수정되어야합니다.

+0

메모리 누수처럼 보입니다. 답변을 주셔서 감사합니다 – oguzh4n

+0

ConcurrentQueue에 대해서는 사실이지만 '누설'은 결코 대기열의 사용되지 않은 부분 이상입니다. 일반적으로'new BlockingCollection (100)'과 같은 상한값을 사용하고, 이것을 영원히 실행할 수 있습니다. –

+0

@Henk, 예, 질문에 코드가 포함되어 있지만 대기열에 바운드가 없으며 처음에는 완전히 채워지고 항목 만 소비 될 가능성이 큽니다. 이 경우 모든 항목이 유출됩니다. – svick

0

가비지 수집기는 항상 메모리를 자동으로 비우지 않습니다. 사용하지 않는 객체를 삭제 한 후 GC.Collect();을 호출하여 가비지 수집을 강제 실행할 수 있습니다.

+0

GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect 시도했다.();''t2.Wait();'행 뒤에는 아무런 문제가 없습니다. – oguzh4n

관련 문제