문제

메모리 할당-해제가 자주 발생하는 오래 지속되는 애플리케이션이 있습니다.malloc 구현이 해제된 메모리를 시스템에 다시 반환합니까?

이 점에서 다음의 행동은 무엇입니까?

  • ptmalloc 1, 2(glibc 기본값) 또는 3
  • dlmalloc
  • tcmalloc(구글 스레드 malloc)
  • 솔라리스 10-11 기본 malloc 및 mtmalloc
  • FreeBSD 8 기본 malloc(jemalloc)
  • malloc을 저장해 두셨나요?

업데이트

낮과 밤의 메모리 소비가 매우 다를 수 있는 애플리케이션이 있는 경우(예:) malloc 중 하나가 해제된 메모리를 시스템에 반환하도록 강제할 수 있습니까?

이러한 반환이 없으면 해제된 메모리는 여러 번 교체되지만 이러한 메모리에는 쓰레기만 포함됩니다.

도움이 되었습니까?

해결책

다음 분석은 glibc(ptmalloc2 알고리즘 기반)에만 적용됩니다.해제된 메모리를 시스템에 다시 반환하는 데 도움이 되는 특정 옵션이 있습니다.

  1. 말롭트() (에 정의됨 malloc.h)는 매개변수 옵션 중 하나를 사용하여 트림 임계값을 설정하는 옵션을 제공합니다. M_TRIM_THRESHOLD, 이는 데이터 세그먼트의 상단에 허용되는 최소 여유 메모리 양(바이트)을 나타냅니다.양이 이 임계값 아래로 떨어지면 glibc가 호출됩니다. brk() 커널에 메모리를 돌려줍니다.

    기본값은 M_TRIM_THRESHOLD Linux에서는 128K로 설정되어 있으므로 더 작은 값을 설정하면 공간이 절약될 수 있습니다.

    환경 변수에 트림 임계값을 설정하면 동일한 동작을 얻을 수 있습니다. MALLOC_TRIM_THRESHOLD_, 소스는 전혀 변경되지 않습니다.

    그러나 예비 테스트 프로그램은 다음을 사용하여 실행됩니다. M_TRIM_THRESHOLD malloc에 ​​의해 할당된 메모리가 시스템으로 반환되더라도 실제 메모리 청크(아레나)의 나머지 부분은 처음에 brk() 유지되는 경향이 있습니다.

  2. 호출을 통해 메모리 영역을 정리하고 사용되지 않은 메모리를 시스템에 다시 제공할 수 있습니다. malloc_trim(pad) (에 정의됨 malloc.h).이 함수는 데이터 세그먼트의 크기를 조정하여 최소한 pad 1페이지 미만의 바이트를 해제할 수 있으면 실패합니다.세그먼트 크기는 항상 한 페이지의 배수이며 i386에서는 4,096바이트입니다.

    이 수정된 동작에 대한 구현은 free() 사용하여 malloc_trim malloc 후크 기능을 사용하여 수행할 수 있습니다.이를 위해서는 핵심 glibc 라이브러리에 대한 소스 코드 변경이 필요하지 않습니다.

  3. 사용하여 madvise() glibc의 무료 구현 내부의 시스템 호출.

다른 팁

대부분의 구현은 전체 "블록"(OS에 적합한 크기)이 해제되어 반환 될 수있는 (비교적 드문) 사례를 식별하는 것을 방해하지 않지만 물론 예외가 있습니다. 예를 들어, 나는 인용합니다 Wikipedia 페이지, OpenBSD에서 :

전화로 free, MUNMAP를 사용하여 프로세스 주소 공간에서 메모리가 해제되고 해제되지 않습니다. 이 시스템은 OpenBSD의 일부로 구현 된 주소 공간 레이아웃 무작위 화 및 갭 페이지 기능을 활용하여 보안을 개선하도록 설계되었습니다. mmap시스템 호출 및 무료 버그를 감지하려면 큰 메모리 할당이 해제 된 후에도 큰 메모리 할당이 완전히 감지되므로 추가로 사용하면 분할 결함과 프로그램 종료가 발생합니다.

그러나 대부분의 시스템은 OpenBSD만큼 보안 중심이 아닙니다.

이것을 알면, 많은 양의 메모리에 대해 알려진 번역 요건이있는 장기 실행 시스템을 코딩 할 때 항상 노력합니다. fork 과정 : 부모는 아동의 결과를 기다립니다 [[일반적으로 파이프]], 자녀는 계산 (메모리 할당 포함)을 수행하고 결과를 반환 한 다음 종료됩니다. 이런 식으로, 나의 장기 실행 프로세스는 기억에 대한 수요가 때때로 "스파이크"사이에 오랜 시간 동안 기억할 수없는 메모리가되지 않을 것입니다. 다른 대안 전략에는 이러한 특수 요구 사항에 대한 사용자 정의 메모리 할당 자로 전환하는 것이 포함됩니다 (C ++는 합리적으로 쉽게 만들어 지지만 Java 및 Python과 같은 가상 머신이있는 언어는 일반적으로 그렇지 않습니다).

나는 OP와 같은 문제를 다루고 있습니다. 지금까지 Tcmalloc에서는 가능해 보입니다. 두 가지 해결책을 찾았습니다.

  1. tcmalloc 링크로 프로그램을 컴파일 한 다음 다음과 같이 시작하십시오.

    env TCMALLOC_RELEASE=100 ./my_pthread_soft
    

    문서 그것을 언급합니다

    합리적인 요금은 범위 [0,10]에 있습니다.

    그러나 10은 나에게 충분하지 않은 것 같습니다 (즉, 나는 변화가 없습니다).

  2. 모든 해방 된 메모리를 해제하는 것이 흥미로울 수있는 코드 어딘가에있는 다음이 코드를 추가하십시오.

    #include "google/malloc_extension_c.h" // C include
    #include "google/malloc_extension.h"   // C++ include
    
    /* ... */
    
    MallocExtension_ReleaseFreeMemory();
    

두 번째 솔루션은 제 경우에는 매우 효과적이었습니다. 첫 번째는 훌륭하지만 성공하지 못하며 예를 들어 올바른 숫자를 찾는 것이 복잡합니다.

내 앱에서 비슷한 문제가 있었는데, 일부 조사 후 어떤 이유로 glibc가 할당 된 객체가 작을 때 (내 경우 120 바이트 미만) 시스템에 메모리를 반환하지 않는다는 것을 알았습니다.
이 코드를보십시오.

#include <list>
#include <malloc.h>

template<size_t s> class x{char x[s];};

int main(int argc,char** argv){
    typedef x<100> X;

    std::list<X> lx;
    for(size_t i = 0; i < 500000;++i){
        lx.push_back(X());
    }

    lx.clear();
    malloc_stats();

    return 0;
}

프로그램 출력 :

Arena 0:
system bytes     =   64069632
in use bytes     =          0
Total (incl. mmap):
system bytes     =   64069632
in use bytes     =          0
max mmap regions =          0
max mmap bytes   =          0

약 64MB는 시스템으로 돌아 오지 않습니다. typedef를 다음으로 변경했을 때typedef x<110> X; 프로그램 출력은 다음과 같습니다.

Arena 0:
system bytes     =     135168
in use bytes     =          0
Total (incl. mmap):
system bytes     =     135168
in use bytes     =          0
max mmap regions =          0
max mmap bytes   =          0

거의 모든 기억이 해방되었습니다. 나는 또한 그것을 사용하는 것을 알아 차렸다 malloc_trim(0) 두 경우 모두 메모리가 시스템에 메모리를 방출했습니다.
다음은 추가 후 출력입니다 malloc_trim 위의 코드에 :

Arena 0:
system bytes     =       4096
in use bytes     =          0
Total (incl. mmap):
system bytes     =       4096
in use bytes     =          0
max mmap regions =          0
max mmap bytes   =          0

당신이 언급 한 것들을 포함하여 모든 '정상적인'malloc의 경우, 메모리는 프로세스에 의해 재사용되도록 해제되지만 전체 시스템으로 돌아 가지 않습니다. 전체 시스템으로 되돌아 가면 프로세스가 종료 될 때만 발생합니다.

당신이 나열하는 것 중에서, Board만이 시스템에 메모리를 반환합니다 ... 그러나 실제로 할 수 있다면 프로그램의 할당 동작에 크게 달려 있습니다.

짧은 답변 : Malloc 서브 시스템이 메모리를 OS로 반환하도록 강제하려면 malloc_trim ()을 사용하십시오. 그렇지 않으면 리턴 메모리의 동작은 구현에 따라 다릅니다.

FreeBSD 12 malloc(3) 용도 제말록 5.1은 다음을 사용하여 해제된 메모리("더티 페이지")를 OS에 반환합니다. madvise(...MADV_FREE).

해제된 메모리는 다음에 의해 제어되는 시간 지연 후에만 반환됩니다. opt.dirty_decay_ms 그리고 opt.muzzy_decay_ms;참조 매뉴얼 페이지부패 기반의 미사용 더티 페이지 제거 구현 관련 문제 상세 사항은.

이전 버전의 FreeBSD에는 이전 버전의 jemalloc이 함께 제공되었습니다. 이 버전도 해제된 메모리를 반환하지만 제거할 대상과 시기를 결정하기 위해 다른 알고리즘을 사용합니다.

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