문제

몇 개의 3차원 배열이 엄청난 양의 메모리를 할당하고 프로그램이 때때로 이를 더 크거나 작은 배열로 교체해야 하고 OutOfMemoryException이 발생하는 문제가 있습니다.

예:5개의 할당된 96MB 배열(200x200x200, 각 항목에 12바이트의 데이터)이 있으며 프로그램은 이를 210x210x210(111MB)로 대체해야 합니다.이는 다음과 유사한 방식으로 수행됩니다.

array1 = new Vector3[210,210,210];

여기서 array1-array5는 이전에 사용된 것과 동일한 필드입니다.이렇게 하면 이전 배열을 가비지 수집 후보로 설정해야 하지만 GC가 충분히 신속하게 작동하지 않고 새 배열을 할당하기 전에 이전 배열을 할당된 상태로 남겨 두므로 OOM이 발생합니다. 반면 새 할당 전에 해제된 경우 공간이 있어야 합니다. 충분한.

내가 찾고 있는 것은 다음과 같은 작업을 수행하는 방법입니다.

GC.Collect(array1) // this would set the reference to null and free the memory
array1 = new Vector3[210,210,210];

전체 가비지 수집이 좋은 생각인지는 잘 모르겠습니다. 해당 코드가 (어떤 상황에서는) 상당히 자주 실행되어야 할 수도 있기 때문입니다.

이를 수행하는 적절한 방법이 있습니까?

도움이 되었습니까?

해결책

이는 원래 질문인 'GC를 강제하는 방법'에 대한 정확한 답변은 아니지만, 문제를 다시 검토하는 데 도움이 될 것이라고 생각합니다.

귀하의 댓글을 확인한 후,

  • GC.Collect() 넣기;도움이 되는 것 같지만 여전히 문제가 완전히 해결되지는 않습니다. 어떤 이유로 약 1.3GB가 할당되면 프로그램이 계속 충돌합니다(저는 System.GC.GetTotalMemory( false )를 사용하고 있습니다.할당된 실제 금액을 찾으려면).

나는 당신이 가지고 있을지도 모른다고 의심 할 것입니다 메모리 조각화.개체가 큰 경우(제대로 기억한다면 .net 2.0 CLR에서 85000바이트, 변경되었는지 여부는 알 수 없음) 개체는 특수 힙에 할당됩니다. LOH(대형 개체 힙).GC는 LOH의 연결할 수 없는 개체에서 사용 중인 메모리를 회수하지만, 압축을 수행하지 않습니다. 성능으로 인해 다른 힙(gen0, gen1 및 gen2)과 마찬가지로 LOH에서도 마찬가지입니다.

큰 개체를 자주 할당하고 할당 해제하면 LOH가 조각화되고 필요한 것보다 총 여유 메모리가 많아도 더 이상 연속된 메모리 공간이 없을 수 있으므로 OutOfMemory 예외가 발생합니다.

현재로서는 두 가지 해결 방법을 생각할 수 있습니다.

  1. 64비트 머신/OS로 전환하여 활용하세요 :) (가장 쉬울 수도 있지만 리소스 제약에 따라 가장 어려울 수도 있습니다)
  2. #1을 수행할 수 없는 경우 먼저 엄청난 양의 메모리를 할당하고 이를 사용하여 조각화를 방지하십시오(실제로는 더 큰 배열에 있는 더 작은 배열을 조작하기 위해 일부 도우미 클래스를 작성해야 할 수도 있음).이는 약간의 도움이 될 수 있지만 문제를 완전히 해결하지 못할 수도 있으며 복잡성을 처리해야 할 수도 있습니다.

다른 팁

LOH(대형 개체 힙) 조각화 문제가 발생한 것 같습니다.

대형 개체 힙

CLR 인사이드 아웃 대형 개체 힙 발견

SOS를 사용하여 Loh 조각화 문제가 있는지 확인할 수 있습니다.

이것을 확인하세요 질문 SOS를 사용하여 loh를 검사하는 방법에 대한 예입니다.

가비지 수집을 강제하는 것은 항상 좋은 생각은 아닙니다. 실제로 어떤 상황에서는 개체의 수명을 늘릴 수 있습니다.필요한 경우 다음을 사용합니다.

array1 = null;
GC.Collect();
array1 = new Vector3[210,210,210];

이것은 단지 대형 개체 힙 조각화에 불과한 것이 아닙니까?85,000바이트보다 큰 개체는 대형 개체 힙에 할당됩니다.GC는 이 힙의 공간을 확보하지만 나머지 개체를 압축하지 않습니다.이로 인해 대형 개체를 성공적으로 할당하기에는 연속 메모리가 부족해질 수 있습니다.

앨런.

제가 추측해야 할 문제는 실제로 Vector3[200,200,200]에서 Vector3[210,210,210]으로 이동한다는 것이 아니라 이 단계 이전에 유사한 이전 단계를 수행했을 가능성이 가장 높다는 것입니다.

 i.e.   
    // first you have
    Vector3[10,10,10];
    // then
    Vector3[20,20,20];
    // then maybe
    Vector3[30,30,30];
    //  .. and so on ..
    //  ...
    // then
    Vector3[200,200,200];
    // and eventually you try
    Vector3[210,210,210] // and you get an OutOfMemoryException..

그것이 사실이라면 더 나은 배분 전략을 제안하겠습니다.초과 할당을 시도해 보세요. 항상 필요한 공간만 할당하는 대신 매번 크기를 두 배로 늘릴 수도 있습니다.특히 이러한 배열이 버퍼를 고정해야 하는 객체에서 사용되는 경우(예:네이티브 코드와 관련이 있는 경우)

따라서 위의 내용 대신 다음과 같은 내용을 사용하십시오.

 // first start with an arbitrary size
 Vector3[64,64,64];
 // then double that
 Vector3[128,128,128];
 // and then.. so in thee steps you go to where otherwise 
 // it would have taken you 20..
 Vector3[256,256,256];

예상치 못한 곳에서 참조되고 있기 때문에 수집되지 않을 수도 있습니다.

테스트로 참조를 다음으로 변경해 보십시오. 약한 참조 대신 OOM 문제가 해결되는지 확인하세요.그렇지 않다면 다른 곳에서 참조하고 있는 것입니다.

나는 당신이하려는 일을 이해하고 즉각적인 가비지 수집을 추진하는 것이 아마도 올바른 접근 방식이 아닐 수도 있습니다 (GC는 그 방식이 미묘하고 빠르게 화를 내기 때문에).

즉, 만약 당신이 원하다 그 기능을 만들어 보는 것은 어떨까요?

public static void Collect(ref object o)
{
    o = null;
    GC.Collect();
}

OutOfMemory 예외는 내부적으로 GC 주기를 자동으로 한 번 트리거하고 실제로 코드에 예외를 발생시키기 전에 할당을 다시 시도합니다.OutOfMemory 예외가 발생할 수 있는 유일한 방법은 너무 많은 메모리에 대한 참조를 보유하는 경우입니다.참조에 null을 할당하여 가능한 한 빨리 참조를 지웁니다.

문제의 일부는 대형 개체 힙에서 단일 연속 메모리 블록으로 표시되는 다차원 배열을 할당한다는 것일 수 있습니다(자세한 내용은 여기).어딘가에 아직 여유 공간이 남아 있더라도 사용할 수 있는 연속된 여유 블록이 없기 때문에 다른 할당이 차단될 수 있습니다. 즉, OOM이 발생합니다.

단일 블록이 아닌 메모리 주위에 배열을 분산시키는 들쭉날쭉한 배열(Vector3[210][210][210])로 할당해 보고 문제가 개선되는지 확인하십시오.

John, 85000바이트보다 큰 개체를 생성하면 개체가 대형 개체 힙에 들어가게 됩니다.대형 개체 힙은 압축되지 않으며 대신 여유 공간이 다시 재사용됩니다.즉, 매번 더 큰 어레이를 할당하면 LOH가 조각화되어 OOM이 발생하는 상황이 발생할 수 있습니다.

OOM 시점에서 디버거를 중단하고 덤프를 얻은 후 연결 버그를 통해 이 덤프를 MS에 제출하면 이것이 사실인지 확인할 수 있습니다(http://connect.microsoft.com) 좋은 시작이 될 것입니다.

제가 확신할 수 있는 것은 GC가 할당 요청을 만족시키기 위해 올바른 일을 할 것이라는 것입니다. 여기에는 GC를 시작하여 새로운 할당 요청을 충족시키기 위해 오래된 쓰레기를 정리하는 것도 포함됩니다.

Stackoverflow에서 메모리 덤프를 공유하는 정책이 무엇인지는 모르겠지만 문제를 더 잘 이해하기 위해 기꺼이 살펴보겠습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top