2011-03-09 6 views
42

Red Gates ANTS 메모리 프로파일 러를 사용하여 메모리 누수를 디버깅했습니다. 계속 경고 메시지를 표시합니다..NET에서 메모리 조각화가 발생하는 이유

메모리 단편화로 인해 사용 가능한 메모리가 너무 많습니다.

또는

메모리 조각화가

나는 OCD를 가지고 있기 때문에

을 할당 할 수있는 가장 큰 개체의 크기에 영향을 미치고,이 문제는 해결해야합니다.

메모리 조각화를 피할 수있는 몇 가지 표준 코딩 방법은 무엇입니까? 일부 .NET 메소드를 통해 조각 모음을 수행 할 수 있습니까? 도움이 될까요?

+6

에 대한 추가 정보를 참조하십시오. 고정 된 메모리 (또는 장면 뒤에서 I/O 버퍼를 핀하는 I/O 함수 사용), 네이티브 할당 자 (예 : COM 작업 할당 자)에서 할당을 사용하거나 많은 수의 대형 개체를 만드는 경우 메모리 조각화가 발생합니다. LOH가 압축되지 않습니다. .NET 가비지 수집기는 이미 세대 별 동적 할당을 압축하므로 여유 공간을 조각 모음하는 부작용이 있습니다. 그게 일어나지 않는다면, 뭔가가 움직이는 것을 방해하기 때문입니다. –

+28

* 강박 신경증 (OCD)이 있으므로이 문제는 해결해야합니다. *이 의견 만있는 경우 * +1. 실제로 문제가 생깁니다. – BrokenGlass

+9

문제가있는 진단 도구를 제거하십시오.메모리 단편화는 삶의 사실이며, 막을 수 없으면 그렇게 할 수 없으며 대폭적으로 비실용적이지 않습니다. 저 단편화 힙 할당자는 이미 Vista 이상에서 기본값입니다. 어쨌든 사용 가능한 주소 공간의 절반 이상을 할당하는 경우에만 돼지가 문제가됩니다. 돼지는 날지 않습니다. –

답변

9

알다시피, 나는 약간의 메모리 프로파일 러를 여기에서 의심합니다. .NET의 메모리 관리 시스템은 실제로 메모리 주위로 이동하여 힙을 조각 모음하려고 시도합니다. (그 때문에 외부 DLL과 공유하기 위해 메모리를 고정해야합니다.)

장기간에 걸쳐 메모리를 많이 할당하면 조각화가 더 자주 발생합니다. 짧은 임시 (짧은) 메모리 요청은 .NET에서 단편화를 일으키지 않습니다.

여기에 대해서도 생각해 볼 가치가 있습니다. .NET의 현재 GC를 사용하면 시간상 가까운 곳에 할당 된 메모리는 일반적으로 공간에서 서로 가깝게 배치됩니다. 조각화의 반대는 어느 것입니다. 즉, 액세스하려는 방식대로 메모리를 할당해야합니다.

관리 코드 만입니까? 아니면 P/Invoke, 관리되지 않는 메모리 (Marshal.AllocHGlobal) 또는 GCHandle.Alloc (obj, GCHandleType.Pinned) 같은 항목이 포함되어 있습니까?

+6

GC는 85KB가 넘는 대형 오브젝트 힙을 압축하지 않습니다. LOH가 단편화되면 조각 모음을 수행 할 방법이 없습니다. –

+0

.NET 4.5.1m에서는 수동으로 LOH를 압축 할 수있는 방법이 있습니다.하지만이 방법은 앱 성능에 큰 타격을 입히는 이유 때문에 강력히 추천합니다. https://blogs.msdn.microsoft.com/mariohewardt/2013/06/26/no-more-memory-fragmentation-on-the-net-large-object-heap/ (다시 반대합니다.) –

10

GC 힙은 대형 개체 할당을 다르게 처리합니다. 그것들을 압축하지는 않지만, 전통적인 비 관리 메모리 저장소처럼 인접한 자유 블록들을 결합합니다. 여기

상세 정보 : http://msdn.microsoft.com/en-us/magazine/cc534993.aspx

그래서 매우 큰 물체로 최선의 전략은 한 번에 할당 한 다음에 보유하고 재사용하는 것입니다.

+1

Out 호기심 때문에 왜 LOH 객체 크기가 4096의 다음 배수로 반올림되지 않는지 궁금합니다. 그것은 마치 일부 OS 컨텍스트에서 압축을 용이하게하는 것처럼 보이며 (단순히 메모리를 복사하는 대신 가상 페이지 포인터를 이동하는 것), 조각화를 크게 줄여줍니다. LOH 객체는 일반적으로 최소 85K이므로 4K 블록까지 반올림하는 오버 헤드는 5 % 이하가됩니다. – supercat

6

.NET Framework 4.5.1에는 가비지 수집 중에 LOH (Large Object Heap)를 명시 적으로 압축 할 수있는 기능이 있습니다.

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

그것은이이 응용 프로그램의 종류에 대한 정보를 가지고 도움이 될 GCSettings.LargeObjectHeapCompactionMode

+0

나는 두 가지 이유에서 앱 성능에 큰 타격을 입는다는 이유로 강하게 권할 것입니다. 1. 시간이 많이 걸립니다. 2. GC가 수집 한 할당 패턴 알고리즘을 모두 지 웁니다. 앱의 평생. 앱이 실행되는 동안 GC는 앱이 메모리를 할당하는 방법을 학습하여 실제로 조정됩니다. 따라서 앱 실행 시간이 길어질수록 (특정 시점까지) 더 효율적입니다. GC.Collect() (또는 그 과부하)를 실행하면 GC가 배운 모든 데이터가 지워 지므로 다시 시작해야합니다. –

+0

@Dave Black, 어디서 그런 정보를 찾았습니까? MSDN에는 LOH 압축이 할당 패턴 알고리즘에 미치는 영향에 대한 정보가 없습니다. – 23W

+1

@ 23W, 나는 팀에서 일하는 사람들을 알고 있습니다. –

관련 문제