2012-06-06 4 views
10

은 내가 스트리밍 할 필요가 거대한 이미지와 함께 작동하는 응용 프로그램이 1.2GB 메모리 예외

  • Memory usage of DotNET app
  • Is there a memory limit for a single .NET process
    • Is There Really A 1.2GB Limit For .NET?
    • 메모리 제한에 대해 읽어보십시오. 단일 프레임으로 비디오를 처리하는 경우와 같습니다. 응용 프로그램에는 약 40 개의 플러그인이 있으며 각 플러그인에는 데이터베이스, 이미지 처리 및 WPF GUI가 포함될 수 있습니다.

      또한 응용 프로그램에는 이전 DotNet Winforms를 사용하는 2 개의 플러그인이 있습니다.

      응용 프로그램을 제외한 모든 응용 프로그램은 RAM이 약 1.2GB 이상입니다. 그런 다음 새 메모리가 할당 된 플러그인의 비정상적인 위치에서 "메모리 부족 예외"가 발생합니다.

      32Bit로 컴파일 된 64Bit 시스템에서 작업하고 있습니다. 나는 무엇을 해야할지 더 이상 알지 못합니다.

      한계가 있습니까? 아니면이를 잡을 수 있습니까?

    +0

    얼마나 많은 사용자가 한계에 부딪 쳤습니까? – Limey

    +0

    나는 그 질문을 이해하지 못한다. 이미지는 1500x1500 픽셀이며 모두 잘 작동합니다. 비디오 스트림의 소스 이미지 해상도가 3500x3500이면 동일한 코드 및 동일한 절차로 응용 프로그램이 메모리 예외와 충돌합니다. 그러나 컴퓨터는 3GB 이상의 RAM을 사용할 수 있으며 무료입니다. – Nasenbaer

    +1

    [ANTS 메모리 프로파일 러] (http://www.red-gate.com/products/dotnet-development/ants-memory-profiler/)와 같이 _memory_ 프로파일 러 (즉, _performance_ 프로파일 러가 아님)를 사용할 것입니다. –

    답변

    19

    모두 사용 가능한 가상 메모리 공간 인을 사용하는 32 비트 프로그램을 작성하는 것은 매우 어렵습니다. 당신은 2 기가 바이트 아래의 벽에 잘 닿을 것입니다. 첫 번째 부족한 부분은 요청 된 크기에 맞게 충분히 큰 가상 메모리입니다. 구멍에 들어가기에 충분히 작은 작은 할당만으로 2GB 제한까지 올릴 수 있습니다.

    이 벽은 비트 맵을 조작하는 프로그램에서 일찍 공격합니다. VM의 큰 덩어리를 소비하여 비트 맵 픽셀을 저장할 수 있으며 인접한 할당이 필요합니다. 이들은 tree이 아니라 array에 저장됩니다. 관리되지 않는 메모리 할당이므로 일반적인 .NET 메모리 프로파일 러는 문제를 보여주기가 쉽지 않습니다.

    주소 공간 조각화에 대해 할 수있는 일은별로 없지만 사용 가능한 모든 VM을 사용할 수 있어야한다는 개념은 잘못되었습니다. post build event에서 editbin.exe을 실행하고 /LARGEADDRESSAWARE 명령 줄 옵션을 사용하면 64 비트 운영 체제에서 더 많은 호흡 공간을 확보 할 수 있습니다. 따라서 프로세스가 64 비트 버전의 Windows에만 해당되며 Windows에서 상위 2GB가 필요하지 않기 때문에 가능한 4 기가 바이트의 VM을 사용할 수 있습니다. 그리고 플랫폼 타겟을 AnyCPU로 변경하는 것은 가상 메모리를 빠르고 쉽게 얻을 수있는 방법입니다.

    0

    OS에서 64Bit 인 경우에도 Windows에서 실행되는 32Bit 응용 프로그램에는 4Gb 주소 공간이 있지만 2Gb 응용 프로그램/2Gb 시스템으로 분할됩니다 (다른 시작 스위치로 3/1로 변경할 수 있음).

    사용중인 총 메모리가 실제로 1.2Gb가 아닌 2Gb 일 가능성이 높습니다.이 1.2Gb 수치는 어떻게 결정합니까? process explorer 도구를 사용하여 응용 프로그램을 보았습니까?

    응용 프로그램을 ANYCPU 또는 64Bit로 변경하면 64Bit OS에서이 제한이 사라집니다 (대량으로 더 큰 값으로 이동 함).

    +7

    정보를 추가하십시오. 2GB는 관리되지 않는 앱용입니다. 관리되는 응용 프로그램의 경우 OOM은 대략 GC 때문에 1.2-1.5GB 정도 발생합니다. 64 비트로 변경하면 문제가 해결 될 수 있지만 종속성이 32 비트 인 경우 불가능할 수 있습니다. –

    0

    결정 성을 높이려면 메모리가 어디에서 끝나는 지 확인하기 위해 통합 테스트를 작성해야합니다. WMemoryProfiler으로 지금 할 수 있습니다.먼저 1500x1500 크기로 이미지를로드하고 모든 것을 정리 한 다음 모든 오브젝트를 알려진 것으로 표시합니다. 그런 다음 큰 이미지를 재배치하고 할당 된 새로운 객체를 확인하고 얼마나 많은 객체가 있고 객체를 소유하고 있는지를 예리하게 관찰합니다.

    많은 외부 모듈이 사용된다고합니다. 아마도 당신은 현명하지 못한 메모리 사용으로 인해 그 중 일부를 버리고 더 나은 것으로 대체해야 할 것입니다. 이제 확인할 수 있습니다.

    한계에 도달 한 경우 이미지를로드 할 수 있고 개발자와 플러그인이 IEnumerable<Image>과 같은 지연 구조를 지원하는 경우 이미지를로드 할 때 이미지를로드 할 시간과 길이를 결정할 수 있습니다 메모리를 확보하는 데 도움이되는 참조를 제거 할 때까지 캐시에 저장하십시오.

    [Test] 
    public void InstanceTracking() 
    { 
        using (var dumper = new MemoryDumper()) // if you have problems use to see the debugger windows true,true)) 
        { 
         TestWith1500x1500(); 
         dumper.MarkCurrentObjects(); 
         TestWith3000x3000(); 
         ILookup<Type, object> newObjects = dumper.GetNewObjects() 
                   .ToLookup(x => x.GetType()); 
    
         // here we do find out which objects are holding most of the memory 
         MemoryStatistics statOld = dumper.GetMemoryStatistics(); 
         foreach (var typeInfo in statOld.ManagedHeapStats 
                .OrderByDescending(x => x.Value.Count)) 
         { 
          Console.WriteLine("Type {0} has {1} instances of total size {2:N0} bytes", 
              typeInfo.Key, 
              typeInfo.Value.Count, 
              typeInfo.Value.TotalSize); 
         } 
    
         // then check with the info from above who is holding the most interesting new objects. 
         Console.WriteLine("New Strings:"); // just an example perhaps you should have a look at the images. 
         foreach (var newStr in newObjects[typeof(string)]) 
         { 
          Console.WriteLine("Str: {0}", newStr); 
         } 
        } 
    }