2010-04-07 4 views
2

나는 꽤 배고픈 응용 프로그램을 가지고있다. 일부 대형 배열에는 많은 양의 데이터가 저장됩니다.OutOfMemoryException

저는 최근에 가끔 OutOfMemoryException을 발견했습니다. 이러한 OutOfMemoryExceptions은 내 응용 프로그램 (ASP.Net)이 사용 가능한 800MB를 모두 소비하기 훨씬 전에 발생합니다. 배열의 크기가 조정 된 코드 영역까지 문제를 추적했습니다. 배열에는 74 바이트 크기의 구조가 포함됩니다. (나는 16bytes보다 큰 구조체를 생성해서는 안된다는 것을 알고 있지만,이 응용 프로그램은 Vb6 응용 프로그램의 포트입니다). 구조체를 클래스로 변경하려고 시도했지만 현재 문제가 해결 된 것으로 보입니다.

클래스를 변경하면 구조체와 배열을 사용할 때 크기를 조정할 때 새 배열을 저장할 메모리 세그먼트가 예약되어야한다는 사실과 관련이 있다고 생각합니다. (예 : (currentArraySize + increaseBySize) * 74)을 찾을 수 없습니다. 이로 인해 OutOfMemoryException이 발생합니다.

배열의 각 요소가 새 개체에 대한 포인터를 저장하는 데 8 바이트 만 필요하기 때문에 클래스에는 해당되지 않습니다.

여기 내 생각이 맞습니까?

답변

2

배열 크기를 조정하면 새 데이터를 저장하고 데이터를 복사하기 위해 새 데이터를 만들고 동시에 동일한 데이터 사본 두 개를 메모리에 저장합니다. 예상했던대로.

구조체를 사용할 때 배열은 struct size * number of elements을 차지합니다. 클래스를 사용하면 포인터 만 포함됩니다.

시간이 지남에 따라 크기가 증가하는 동일한 시나리오가 있으므로 크기 조정 및 복사를 피하기 위해 예상되는 항목 수로 초기화하는 것이 좋습니다.

32 비트 시스템에서는 800 메가 바이트에서 벗어날 수 있습니다. 시도 할 수있는 한 가지 해결책은 디스크에 구조체를 추가하고 필요할 때 읽을 수있는 방법입니다. 파일 크기가 고정되어 있으므로 파일에서 올바른 위치로 쉽게 이동할 수 있습니다.

대용량 데이터 처리를위한 Codeplex 프로젝트가 있습니다. 자동 증가 가능성이있는 Array 유형을 가지고 있기 때문에 메모리에 다시 저장하는 것과 관련된 문제가 발생하면 시나리오를 도울 수 있습니다.

3

배열 저장 방법에 대한 가정은 정확합니다. 구조체에서 클래스로 변경하면 각 인스턴스에 약간의 오버 헤드가 추가되고 참조를 통해 모든 데이터를 수집해야하므로 지역 이점을 잃어 버릴 수 있습니다. 그러나 관찰 한 바와 같이 지금은 메모리 문제를 해결할 수 있습니다.

2

발생하는 문제는 모든 메모리가 실제로 사용되는 정상 메모리 부족 조건보다 큰 개체 힙의 조각화로 인해 발생할 수 있습니다.

큰 고정 단위보다는 작은 임의 단위로 배열을 증가하는 것처럼 간단 할 수 http://msdn.microsoft.com/en-us/magazine/cc534993.aspx

솔루션 표시되도록 배열은 새로운 큰 배열을 위해 재사용 할 수 LOH 메모리의 블록을 해제 같다.

구조체가 배열 자체에 저장되는 동안 클래스가 작은 개체 힙의 작은 개체가 될 때까지 구조체> 클래스 문제를 설명 할 수도 있습니다.

+0

GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; GC.Collect(); 

더의 정보를 참조하십시오. 클래스를 사용하도록 변경했을뿐만 아니라 배열을 늘리는 전략도 변경했습니다. 한 번에 10000 개 요소가 증가했습니다. 이제 일반 목록과 동일한 전략을 사용하고 있습니다. 즉 필요할 때 배열의 크기를 두 배로 늘릴 수 있습니다. – Andrew

관련 문제