Sarà malloc implementazioni di ritorno libero-ed indietro la memoria di sistema?
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.
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:
-
mallopt () (definito in
malloc.h
) non fornisce un'opzione per impostare il valore di soglia rivestimento utilizzando una delle opzioni parametroM_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 invocabrk()
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 tramitebrk()
tende ad essere mantenuta. -
E 'possibile ritagliare l'arena di memoria e dare qualsiasi memoria non utilizzata di nuovo al sistema chiamando
malloc_trim(pad)
(definito inmalloc.h
). Questa funzione ridimensiona il segmento di dati, lasciando almeno bytepad
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()
usandomalloc_trim
potrebbe essere fatto utilizzando la funzionalità gancio malloc. Ciò non richiederebbe alcuna modifica al codice sorgente alla libreria di base glibc. -
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 dimmap
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:
-
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).
-
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.