Domanda

Ho un lungo soggiorno applicazione con frequenti di allocazione della memoria-la deallocazione.Qualsiasi malloc attuazione di ritorno liberato di memoria del sistema?

Che cosa è, in questo senso, il comportamento di:

  • ptmalloc 1, 2 (glibc default) o 3
  • dlmalloc
  • tcmalloc (google filettato malloc)
  • solaris 10-11 default malloc e mtmalloc
  • FreeBSD 8 di default malloc (jemalloc)
  • Hoard malloc?

Aggiornamento

Se ho un'applicazione in cui il consumo di memoria possono essere molto diversa nelle ore diurne e notturne (ad esempio), si può forzare qualsiasi di malloc per tornare liberato la memoria di sistema?

Senza un tale ritorno di memoria liberata verranno scambiati e in molte volte, ma di memoria contiene solo spazzatura.

È stato utile?

Soluzione

L'analisi che segue si applica solo alle glibc (sulla base di un algoritmo ptmalloc2). Ci sono alcune opzioni che sembrano utili per restituire la memoria liberata di nuovo al sistema:

  1. mallopt () (definito in malloc.h) non fornisce un'opzione per impostare il valore di soglia rivestimento utilizzando una delle opzioni parametro M_TRIM_THRESHOLD, ciò indica la quantità minima di memoria libera (in byte) consentita nella parte superiore del segmento di dati. Se la quantità scende al di sotto di questa soglia, glibc invoca brk() di restituire la memoria al kernel.

    Il valore predefinito di M_TRIM_THRESHOLD in Linux è impostato su 128K, l'impostazione di un valore più piccolo potrebbe risparmiare spazio.

    Lo stesso comportamento potrebbe essere ottenuto impostando il valore di soglia assetto nell'ambiente MALLOC_TRIM_THRESHOLD_ variabile, senza modifiche sorgente assolutamente.

    Tuttavia, programmi di test preliminari eseguiti utilizzando M_TRIM_THRESHOLD ha dimostrato che, anche se la memoria allocata da malloc fa tornare al sistema, la porzione rimanente del blocco effettiva di memoria (scena) inizialmente richiesta tramite brk() tende ad essere mantenuta.

  2. E 'possibile ritagliare l'arena di memoria e dare qualsiasi memoria non utilizzata di nuovo al sistema chiamando malloc_trim(pad) (definito in malloc.h). Questa funzione ridimensiona il segmento di dati, lasciando almeno byte pad alla fine di esso e in mancanza se meno di una pagina valore di byte può essere liberato. dimensione del segmento è sempre un multiplo di una pagina, che è di 4.096 byte su i386.

    L'attuazione di questo comportamento modificata free() usando malloc_trim potrebbe essere fatto utilizzando la funzionalità gancio malloc. Ciò non richiederebbe alcuna modifica al codice sorgente alla libreria di base glibc.

  3. utilizzando chiamata di sistema madvise() all'interno della libera implementazione di glibc.

Altri suggerimenti

La maggior parte delle implementazioni non si preoccupano identificare quei casi (relativamente rari) in cui interi "blocchi" (di qualsiasi dimensione adatta al sistema operativo) sono stati liberati e potranno essere restituiti, ma ci sono ovviamente delle eccezioni. Per esempio, cito da pagina di Wikipedia , in OpenBSD:

  

Su una chiamata a free, la memoria viene rilasciata   e non mappato dall'indirizzo processo   spazio utilizzando munmap. Questo sistema è   progettato per migliorare la sicurezza, prendendo   vantaggio del layout spazio di indirizzi   randomizzazione e Gap caratteristiche pagina   implementato come parte di mmap di OpenBSD   chiamata di sistema, e di individuare   use-after-free bug-come una grande memoria   allocazione è completamente mappato   dopo che è liberato, utilizzare ulteriori cause   un errore di segmentazione e la cessazione   del programma.

La maggior parte dei sistemi non sono così incentrata sulla sicurezza come OpenBSD, però.

Sapendo questo, quando sto codifica di un sistema di lunga durata che ha un requisito nota-to-be-transitoria per una grande quantità di memoria, cerco sempre di fork il processo: il genitore poi aspetta solo per i risultati di il bambino [[tipicamente su un tubo]], il bambino fa il calcolo (inclusa l'allocazione di memoria), restituisce i risultati [[su detto tubo]], quindi termina. In questo modo, il mio processo di lunga esecuzione non sarà inutilmente monopolizzavano memoria durante i lunghi tempi tra occasionali "picchi" nella sua richiesta di memoria. Altre strategie alternative includono il passaggio ad un allocatore di memoria su misura per tali esigenze particolari (C ++ rende ragionevolmente facile, anche se le lingue con le macchine virtuali sotto come Java e Python di solito non lo fanno).

ho a che fare con lo stesso problema come l'OP. Finora, sembra possibile con tcmalloc. Ho trovato due soluzioni:

  1. compilare il programma con tcmalloc collegato, poi lanciarlo come:

    env TCMALLOC_RELEASE=100 ./my_pthread_soft
    

    la documentazione afferma che

      

    Le tariffe ragionevoli sono nel range [0,10].

    ma 10 non sembra sufficiente per me (cioè non vedo nessun cambiamento).

  2. trova da qualche parte nel codice in cui sarebbe interessante per liberare tutta la memoria liberata, e quindi aggiungere questo codice:

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

La seconda soluzione è stata molto efficace nel mio caso; Il primo sarebbe grande, ma non è un grande successo, è complicato trovare il giusto numero per esempio.

Ho avuto un problema simile nella mia app, dopo alcune indagini ho notato che per qualche motivo glibc non restituisce memoria al sistema quando gli oggetti allocati sono piccole (nel mio caso meno di 120 byte).
Guardate questo codice:  

#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;
}

l'output del programma:

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

circa 64 MB non sono tornare al sistema. Quando ho cambiato typedef per: l'output del programma typedef x<110> X; simile a questo:

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

quasi tutta la memoria è stata liberata. Ho anche notato che utilizzando malloc_trim(0) in entrambi i casi ha rilasciato la memoria di sistema.
Qui è uscita dopo aver aggiunto malloc_trim al codice di cui sopra:

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

Per tutti i 'normali' mallocs, compresi quelli che hai citato, la memoria viene rilasciata per essere riutilizzato per il processo, ma non indietro a tutto il sistema. Rilasciando di nuovo a tutto il sistema si verifica solo quando si elabora è finalmente terminato.

di quelli che la lista, solo Hoard tornerà memoria al sistema ... ma se si può realmente fare che dipenderà molto sulle scelte di del programma.

La risposta breve: Per forzare sottosistema malloc per tornare la memoria a OS, utilizzare malloc_trim (). In caso contrario, il comportamento della memoria di ritorno è a carico di attuazione.

FreeBSD 12 malloc(3) utilizza jemalloc 5.1, che restituisce alla memoria liberata ("le pagine sporche") per il sistema operativo utilizzando madvise(...MADV_FREE).

Liberata la memoria viene restituito solo dopo un tempo di ritardo controllato da opt.dirty_decay_ms e opt.muzzy_decay_ms;vedere la pagina di manuale e questo problema sull'attuazione di decadimento a base inutilizzati pagina dirty spurgo per ulteriori dettagli.

Precedenti versioni di FreeBSD fornito con le versioni precedenti di jemalloc, che torna alla memoria liberata, ma utilizza un diverso algoritmo per decidere cosa eliminare e quando.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top