문제

메모리 할당 실패로 인해 장기 실행 서버 프로세스(Windows Server 2003에서 실행)에서 예외가 발생하는 문제가 가끔 발생했습니다.우리는 메모리 조각화로 인해 이러한 할당이 실패하고 있다고 의심합니다.

따라서 우리는 도움이 될 수 있는 몇 가지 대체 메모리 할당 메커니즘을 조사해 왔으며 누군가가 나에게 가장 좋은 것을 말해 줄 수 있기를 바랍니다.

1) 윈도우를 사용하세요 낮은 조각화 힙

2) Jemalloc - 다음에 사용된 것과 같습니다. 파이어폭스 3

3) 더그 리의 malloc

우리의 서버 프로세스는 크로스 플랫폼 C++ 코드를 사용하여 개발되었으므로 모든 솔루션도 이상적으로 크로스 플랫폼이 될 것입니다(*nix 운영 체제가 이러한 유형의 메모리 조각화로 어려움을 겪고 있습니까?).

또한 LFH가 이제 Windows Server 2008/Vista의 기본 메모리 할당 메커니즘이라고 생각하는 것이 맞습니까?...고객이 단순히 서버 OS를 업그레이드하면 현재 문제가 "사라질"까요?

도움이 되었습니까?

해결책

첫째, 리소스 유출을 제안한 다른 포스터에 동의합니다.먼저 그것을 배제하고 싶습니다.

현재 사용하고 있는 힙 관리자가 힙에서 사용 가능한 실제 전체 여유 공간을 덤프할 수 있는 방법을 갖고 있기를 바랍니다. 무료 블록) 및 분할된 총 블록 수도 표시됩니다.평균 여유 블록 크기가 힙의 전체 여유 공간에 비해 상대적으로 작은 경우 조각화 문제가 있는 것입니다.또는 가장 큰 여유 블록의 크기를 덤프하고 이를 총 여유 공간과 비교할 수 있다면 동일한 결과를 얻을 수 있습니다.가장 큰 여유 블록은 전체 블록에 비해 작습니다. 무료 조각화가 발생하는 경우 모든 블록에서 사용할 수 있는 공간입니다.

위의 내용을 명확히 하기 위해 모든 경우에 대해 이야기하고 있습니다. 무료 힙에 할당된 블록이 아니라 힙에 있는 블록입니다.어떠한 경우에도 위의 조건이 충족되지 않으면 하다 일종의 누출 상황이 있습니다.

따라서 누출을 배제한 후에는 더 나은 할당자를 사용하는 것을 고려할 수 있습니다. Doug Lea의 malloc 질문에서 제안된 것은 일반적인 용도의 애플리케이션에 아주 좋은 할당자이며 매우 강력합니다. 최대 그 시간의.다시 말해, 대부분의 모든 응용 프로그램에서 매우 잘 작동하도록 오랜 시간 테스트를 거쳤습니다.그러나 이상적인 알고리즘은 없습니다. 모두 애플리케이션 및 모든 관리 알고리즘 접근 방식은 해당 설계에 대한 올바른 병리학적 조건으로 인해 중단될 수 있습니다.

조각화 문제가 발생하는 이유는 무엇입니까? - 조각화 문제의 원인은 다음과 같습니다. 원인 애플리케이션의 동작에 따라 달라지며 동일한 메모리 영역에서 크게 다른 할당 수명과 관련이 있습니다.즉, 일부 객체는 정기적으로 할당되고 해제되는 반면 다른 유형의 객체는 모두 동일한 힙에 오랜 시간 동안 유지됩니다. 수명이 더 긴 객체는 경기장의 더 넓은 영역에 구멍을 뚫어 해제된 인접한 블록을 병합합니다.

이러한 유형의 문제를 해결하기 위해 할 수 있는 가장 좋은 방법은 힙을 수명이 보다 유사한 하위 경기장으로 논리적으로 나누는 것입니다.실제로 임시 힙과 영구 힙 또는 비슷한 수명의 항목을 그룹화하는 힙이 필요합니다.

다른 사람들은 문제를 해결하기 위해 할당 크기를 더 유사하거나 동일하게 만드는 또 다른 접근 방식을 제안했지만 이는 내부 조각화라는 다른 유형의 조각화를 생성하기 때문에 덜 이상적입니다. 이는 사실상 낭비되는 공간입니다. 필요한 것보다 더 많은 메모리를 블록에 할당합니다.

또한 Doug Lea와 같은 좋은 힙 할당자를 사용하면 블록 크기를 더 유사하게 만드는 것이 불필요합니다. 왜냐하면 할당자는 이미 malloc( ) - 실제로 그의 힙 관리자는 애플리케이션이 조정할 수 있는 것보다 훨씬 더 강력하게 자동으로 이를 수행합니다.

다른 팁

내 생각엔 당신이 실수로 메모리 누수를 너무 일찍 배제한 것 같아요.아주 작은 메모리 누수라도 심각한 메모리 조각화를 일으킬 수 있습니다.

애플리케이션이 다음과 같이 동작한다고 가정합니다.
10MB 할당
1바이트 할당
무료 10MB
(앗, 우리는 1바이트를 해제하지 않았지만 작은 1바이트는 누가 신경쓰나요?)

이건 아주 작은 누수 같은데, 할당된 총 메모리 크기만 모니터링할 때는 거의 눈치채지 못할 것입니다..하지만 이 누수로 인해 결국 애플리케이션 메모리는 다음과 같이 보입니다.
.
.
무료 – 10MB
.
.
[할당됨 -1바이트]
.
.
무료 – 10MB
.
.
[할당됨 -1바이트]
.
.
무료 – 10MB
.
.

이 누출은 눈에 띄지 않을 것입니다 ...11MB를 할당하고 싶을 때까지
미니 덤프에 전체 메모리 정보가 포함되어 있다고 가정하면 다음을 사용하는 것이 좋습니다. 디버그 진단 누출 가능성을 발견합니다.생성된 메모리 보고서에서 할당 횟수(크기 아님)를 주의 깊게 검토하세요..

당신이 제안한 것처럼 Doug Lea의 malloc이 잘 작동할 수도 있습니다.크로스 플랫폼이며 배송 코드에 사용되었습니다.최소한 테스트를 위해 코드에 통합하기가 쉬워야 합니다.

수년간 고정 메모리 환경에서 작업해 본 결과, 이러한 상황은 고정되지 않은 환경에서도 확실히 문제가 됩니다.우리는 CRT 할당자가 성능(속도, 낭비되는 공간의 효율성 등) 측면에서 매우 나쁜 경향이 있다는 것을 발견했습니다.나는 장기간에 걸쳐 좋은 메모리 할당자가 광범위하게 필요하다면 직접 작성해야 한다고 굳게 믿습니다(또는 dlmalloc과 같은 것이 작동하는지 확인해야 합니다).비결은 할당 패턴에 맞는 무언가를 작성하는 것이며, 이는 거의 모든 것과 마찬가지로 메모리 관리 효율성과 더 관련이 있습니다.

dlmalloc을 사용해 보세요.나는 확실히 엄지손가락을 치켜세운다.조정도 상당히 가능하므로 일부 컴파일 시간 옵션을 변경하면 효율성을 높일 수 있습니다.

솔직히 말해서 새로운 OS 구현으로 "사라지는" 것에 의존해서는 안됩니다.N년 후 서비스 팩, 패치 또는 또 다른 새로운 OS로 인해 문제가 더욱 악화될 수 있습니다.다시 말하지만, 강력한 메모리 관리자가 필요한 애플리케이션의 경우 컴파일러에서 사용할 수 있는 기본 버전을 사용하지 마세요.다음에 적합한 것을 찾으세요. 당신의 상황.dlmalloc으로 시작하고 이를 조정하여 상황에 가장 적합한 동작을 얻을 수 있는지 확인하십시오.

할당 취소 할당량을 줄임으로써 조각화를 줄이는 데 도움이 될 수 있습니다.

예를 들어서버 측 스크립트를 실행하는 웹 서버의 경우 페이지를 출력할 문자열을 생성할 수 있습니다.모든 페이지 요청에 대해 이러한 문자열을 할당하고 할당 취소하는 대신 풀을 유지하면 더 필요할 때만 할당하고 할당을 취소하지 않습니다. 즉, 잠시 후 더 이상 할당하지 않는 상황이 발생한다는 의미입니다. 충분한)

_CrtDumpMemoryLeaks()를 사용할 수 있습니다.디버그 빌드를 실행할 때 디버그 창에 메모리 누수를 덤프하는 것은 Visual C 컴파일러에만 해당된다고 생각합니다.(crtdbg.h에 있습니다)

조각화를 의심하기 전에 누출을 의심하겠습니다.

메모리 집약적인 데이터 구조의 경우 재사용 가능한 스토리지 풀 메커니즘으로 전환할 수 있습니다.힙이 아닌 스택에 더 많은 것을 할당할 수도 있지만 실제로는 큰 차이가 없을 것 같습니다.

나는 valgrind와 같은 도구를 실행하거나 집중적인 로깅을 수행하여 공개되지 않는 리소스를 찾습니다.

@nsaners - 문제는 메모리 조각화 때문이라고 확신합니다.우리는 분석했습니다 미니 덤프 이는 큰(5-10MB) 메모리 덩어리가 할당될 때 문제가 있음을 나타냅니다.또한 메모리 누수를 확인하기 위해 프로세스(현장 및 개발 중)를 모니터링했지만 아무 것도 감지되지 않았습니다(메모리 공간은 일반적으로 매우 낮습니다).

일반적으로 그렇게 나쁘지는 않지만 문제는 Unix에서 발생합니다.

낮은 조각화 힙이 우리에게 도움이 되었지만 동료들은 다음과 같이 맹세합니다. 스마트 힙(수년 동안 몇 가지 제품에서 크로스 플랫폼으로 사용되었습니다.)안타깝게도 다른 상황으로 인해 이번에는 Smart Heap을 사용할 수 없었습니다.

우리는 또한 블록/청크를 할당하고 범위에 정통한 풀/전략, 즉 장기적인 것, 여기에 전체 요청, 단기적인 것들 등을 보았습니다.

평소와 마찬가지로 속도를 얻기 위해 메모리를 낭비할 수 있습니다.

이 기술은 범용 할당자에는 유용하지 않지만 그만한 역할을 합니다.

기본적으로 아이디어는 모든 할당이 동일한 크기인 풀에서 메모리를 반환하는 할당자를 작성하는 것입니다.어떤 블록도 다른 블록만큼 좋기 때문에 이 풀은 결코 조각화될 수 없습니다.서로 다른 크기의 청크로 여러 풀을 생성하고 요청된 양보다 여전히 큰 가장 작은 청크 크기 풀을 선택하여 메모리 낭비를 줄일 수 있습니다.나는 이 아이디어를 사용하여 O(1)에서 실행되는 할당자를 만들었습니다.

간단하고 빠르며 지저분한 해결책은 애플리케이션을 다음과 같이 분할하는 것입니다. 여러 프로세스, 프로세스를 생성할 때마다 새로운 HEAP를 얻어야 합니다.

메모리와 속도가 약간 저하될 수 있지만(스왑) 빠른 하드웨어와 큰 RAM이 도움이 될 수 있습니다.

이것은 스레드가 아직 존재하지 않았던 시절의 데몬을 사용한 오래된 UNIX 트릭이었습니다.

Win32에 대해 이야기하는 경우 LARGEADDRESSAWARE를 사용하여 무언가를 짜낼 수 있습니다.~1GB의 추가 조각 모음 메모리가 있으므로 애플리케이션에서 조각 모음 시간이 길어집니다.

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