2010-02-12 4 views
4

내 응용 프로그램에서 메모리 성능을 향상시켜야하며 메모리 조각화에 문제가 있음을 알 수 있습니다.큰 배열의 메모리 누수 - IList를 서브 클래 싱하면 해결할 수 있습니까?

나는 레드 게이트의 앤드류 헌터에서 interesting article on large objects 읽었습니다, 그가 추천하는 솔루션 중 하나입니다 : 대형 데이터 구조는 오랜 시간 동안 을 살 필요, 특히 경우 가

경우 시간이 지남에 따라 크기가 커질 필요가있는 경우 가장 좋은 방법은 단순히 데이터 구조를 사용하거나 다른 데이터 구조로 저장하는 것입니다. 그들이 대형 개체 힙에 넣어 그래서 저장소에 매우 효과적인 방법은 10 만 개 항목이 저장소에 각각 10,000 요소를 포함 10 개 배열 수 있습니다 문제가 발생할 수 있습니다 전에 배열 는 최대 약 10,000 요소를 포함 할 수 있습니다 : 없음 큰 개체 힙 에 끝날 것이므로 조각화가 발생하지 않습니다. 이것은 IList 서브 클래스로 쓰여질 수 있으므로 은 투명하게 삭제됩니다. 기존 코드를 바꿉니다.

코드에서 제안 사항을 어떻게 구현합니까?

내 프로그램이 열릴 때마다 잔여 메모리를 남기는 객체가있는 매우 복잡한 형태입니다. 일 수있는 복잡한 목록을 찾았습니다.이 원인이 될 수 있으며 제안 사항을 구현하고 싶습니다. 이 문제를 해결

+1

궁금한 점은 성능 병목 현상이 조각화로 인한 것일 수 있습니다. –

+0

그의 튜토리얼 (http://j.mp/c9etnh)에서 "ANTS Memory Profiler"를 사용하면 "가장 큰 프리 블록 크기는 작지만 모든 .NET 힙 크기의 여유 공간이 큽니다." 사용되지 않은 메모리가 많아 연속 사용하지 않는 메모리 블록이 작기 때문에 메모리가 효율적으로 사용되지 않기 때문에 메모리가 부족할 위험이 있습니다. " 내 문제 인 것 같습니다. 그리고 내 컬렉션에는 LOH의 한계 인 85K를 넘는 많은 요소가 있습니다. 너무 참조하는 이벤트 처리를 조사하고 있습니다 ... – rubdottocom

+0

죄송합니다, 아마도 귀하의 게시물을 오해했을 것입니다. "기억 성능"을 말할 때 당신이 의미하는 바를 자세히 설명해 주시겠습니까? 메모리 예외 상황에서 빠져 나왔습니까? –

답변

5

무슨에 대한 목록을 사용하여 잘못 즉, IList의 구현하지만, 아무것도하고 파티션을 직접 수행 할 수 있습니다하지만 당신은 투명하게 작업을 수행하려는 경우 :.?.

가 IList의 구현 (그것이 단지 인터페이스, 아무것도 그것에 대해 특별한. 어쩌면 내가 질문을 이해가 안돼?) 및 원하는 크기의 배열로 백업하십시오. Get() 그런 다음 원하는 항목이 들어있는 배열의 인덱스로 index/sizeOfArrays을 가져와 해당 배열의 index % sizeOfArrays 번째 항목을 반환합니다.


재미 있기 때문에, 나는 게으른 금요일이기 때문에, 나는 무엇인가 썼다. 참고 :

  • 모르겠어요

    • 내가 그것을 테스트하지 않았다
    • 나는이 메모리 조각화를 피하는 데 도움이 될 것을 당신의 인용 특허 청구 범위의 correctnes에 언급 할 수
    • , 나는 맹목적으로 요청 보았다 단지 List 나 다른 콜렉션이 이미 똑똑하다면
    • 나는 당신에게 맞지 않을 수도있는 몇 가지 결정을 내 렸습니다. (배열을 사용하고 있다면 코드에서 이것을 맹목적으로 삭제할 수 없습니다.) Item 구현, 특히 세터 예 :

    그건 그렇고, 여기 주말 내 동기 적자를 줄인 출발점이 있습니다. 나는 친애하는 독자 (또는 OP)에게 운동으로서의 흥미있는 약간의 방법을 남겼다..;-)

    public class PartitionList<T> : IList<T> { 
        private readonly int _maxCountPerList; 
        private readonly IList<IList<T>> _lists; 
    
        public PartitionList(int maxCountPerList) { 
         _maxCountPerList = maxCountPerList; 
         _lists = new List<IList<T>> { new List<T>() }; 
        } 
    
        public IEnumerator<T> GetEnumerator() { 
         return _lists.SelectMany(list => list).GetEnumerator(); 
        } 
    
        IEnumerator IEnumerable.GetEnumerator() { 
         return GetEnumerator(); 
        } 
    
        public void Add(T item) { 
         var lastList = _lists[_lists.Count - 1]; 
         if (lastList.Count == _maxCountPerList) { 
          lastList = new List<T>(); 
          _lists.Add(lastList); 
         } 
         lastList.Add(item); 
        } 
    
        public void Clear() { 
         while (_lists.Count > 1) _lists.RemoveAt(1); 
         _lists[0].Clear(); 
        } 
    
        public bool Contains(T item) { 
         return _lists.Any(sublist => sublist.Contains(item)); 
        } 
    
        public void CopyTo(T[] array, int arrayIndex) { 
         // Homework 
         throw new NotImplementedException(); 
        } 
    
        public bool Remove(T item) { 
         // Evil, Linq with sideeffects 
         return _lists.Any(sublist => sublist.Remove(item)); 
        } 
    
        public int Count { 
         get { return _lists.Sum(subList => subList.Count); } 
        } 
    
        public bool IsReadOnly { 
         get { return false; } 
        } 
    
        public int IndexOf(T item) { 
         int index = _lists.Select((subList, i) => subList.IndexOf(item) * i).Max(); 
         return (index > -1) ? index : -1; 
        } 
    
        public void Insert(int index, T item) { 
         // Homework 
         throw new NotImplementedException(); 
        } 
    
        public void RemoveAt(int index) { 
         // Homework 
         throw new NotImplementedException(); 
        } 
    
        public T this[int index] { 
         get { 
          if (index >= _lists.Sum(subList => subList.Count)) { 
           throw new IndexOutOfRangeException(); 
          } 
          var list = _lists[index/_maxCountPerList]; 
          return list[index % _maxCountPerList]; 
         } 
         set { 
          if (index >= _lists.Sum(subList => subList.Count)) { 
           throw new IndexOutOfRangeException(); 
          } 
          var list = _lists[index/_maxCountPerList]; 
          list[index % _maxCountPerList] = value; 
         } 
        } 
    }