Frage

Ich habe eine langlebige Anwendung mit häufigen Speicherzuordnung-Freigabe. Erzielt ein malloc Implementierung Rückkehr freigegebenen Speicher an das System zurück?

Was ist in dieser Hinsicht das Verhalten:

  • ptmalloc 1, 2 (glibc default) oder 3
  • dlmalloc
  • tcmalloc (google Gewinde malloc)
  • solaris 10-11 Standard malloc und mtmalloc
  • FreeBSD 8 default malloc (jemalloc)
  • Hoard malloc?

Update

Wenn ich eine Anwendung, deren Speicherverbrauch haben kann Tag und Nacht sehr unterschiedlich sein (z), kann ich jede von malloc-Kraft befreit Speicher an das System zurück?

Ohne eine solche Rückkehr freigegebenen Speicher ausgelagert und in viele Male werden, aber solche Speicher enthält nur Müll.

War es hilfreich?

Lösung

Die folgende Analyse bezieht sich nur auf glibc (basierend auf ptmalloc2 Algorithmus). Es gibt einige Optionen, die nützlich erscheinen die freigegebenen Speicher zurück zu dem System zurück:

  1. mallopt () (definiert in malloc.h) eine Option vorsieht die Trimmung Schwellwerts unter Verwendung einer der Parameter M_TRIM_THRESHOLD Option zu setzen, zeigt dies die minimale Menge an freiem Speicher (in Byte) an der Oberseite gestattet des Datensegments. Wenn die Menge unter dieser Schwelle, ruft glibc brk() Speicher an den Kernel zurück zu geben.

    Der Standardwert von M_TRIM_THRESHOLD in Linux auf 128K eingestellt ist, könnte einen kleineren Wert einstellen Platz sparen.

    Das gleiche Verhalten, indem trim Grenzwert in der Umgebungsvariablen MALLOC_TRIM_THRESHOLD_, ohne Quelle Änderungen absolut erreicht werden könnte.

    Allerdings vorläufigen Testprogramme M_TRIM_THRESHOLD laufen mit hat gezeigt, dass, obwohl die von malloc Speicher an das System zurückkehrt, der verbleibende Teil des eigentlichen Teil des Speichers (die Arena) zunächst über brk() angefordert werden beibehalten tendiert.

  2. Es ist möglich, die Speicher Arena und geben nicht verwendeten Speicher zurück an das System durch Aufruf malloc_trim(pad) (definiert in malloc.h) zu trimmen. Diese Funktion ändert die Größe des Datensegments, mindestens pad Bytes am Ende davon zu verlassen, und andernfalls, wenn weniger als eine Seite im Wert von Bytes kann befreit werden. Segmentgröße ist immer ein Vielfaches von einer Seite, die 4.096 Bytes auf i386 ist.

    Die Implementierung für dieses modifizierte Verhalten von free() malloc_trim verwendet, könnte die malloc Haken Funktionalität getan werden. Dies würde keine Änderungen am Quellcode an den Kern glibc-Bibliothek benötigen.

  3. mit madvise() Systemaufruf innerhalb der freien Implementierung von glibc.

Andere Tipps

Die meisten Implementierungen nicht die Mühe, diese (relativ seltenen) Fällen identifiziert, wo ganze „Blöcke“ (gleich welcher Größe passt das OS) befreit wurden und zurückgeführt werden könnte, aber es gibt natürlich Ausnahmen. Zum Beispiel, ich zitiere aus der Wikipedia-Seite , in OpenBSD:

  

Bei einem Aufruf zu free, Speicher wird freigegeben   und nicht zugeordnete Adresse aus dem Prozess   Raum mit munmap. Dieses System ist   entwickelt die Sicherheit zu verbessern, indem   Vorteil des Adressraums Layout   Randomisierung und Lücke Seite Merkmale   als Teil von OpenBSD mmap umgesetzt   Systemaufruf, und zu erfassen,   use-after-free bugs-als großer Speicher   Zuordnung ist völlig unmapped   nachdem es freigegeben wird, weitere Ursachen verwenden   ein Segmentierungsfehler und Kündigung   des Programms.

Die meisten Systeme sind nicht als sicherheitsorientierten als OpenBSD, though.

Mit diesem Wissen, wenn ich Codierung ein mit langen Laufzeit-System, das eine bekannte seinen flüchtigen Voraussetzung für eine große Menge an Speichern, ich versuche immer, um den Prozess zu fork: die Eltern dann wartet nur für die Ergebnisse aus das Kind [[typischerweise auf einem Rohr]], hat das Kind die Berechnung (einschließlich Speicherzuweisung), um die Ergebnisse zurückgibt [[auf dem Rohr]], dann beendet. Auf diese Weise, mein lang laufender Prozess wird nicht unnütz Speicher während der langen Zeit zwischen gelegentlichen „Spitzen“ in der Nachfrage nach Speicher hogging sein. Andere alternative Strategien umfassen für solche speziellen Anforderungen an eine benutzerdefinierte Speicherzuordner Schalen (C ++ macht es relativ einfach, wenn auch Sprachen mit virtuellen Maschinen unter wie Java und Python normalerweise nicht).

ich mit dem gleichen Problem wie die OP zu tun habe. Bisher scheint es möglich, mit tcmalloc. Ich fand zwei Lösungen:

  1. kompilieren Ihr Programm mit tcmalloc verknüpft, dann starten Sie es wie:

    env TCMALLOC_RELEASE=100 ./my_pthread_soft
    

    die Dokumentation dass erwähnt

      

    Angemessene Preise liegen im Bereich [0,10].

    aber 10 nicht genug scheint für mich (das heißt ich sehe keine Veränderung).

  2. irgendwo in Ihrem Code finden, wo es interessant wäre, alle freigegebenen Speicher freizugeben, und dann diesen Code hinzu:

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

Die zweite Lösung ist in meinem Fall sehr effektiv; die ersten groß sein würde, aber es ist nicht sehr erfolgreich, es ist kompliziert die richtige Anzahl beispielsweise zu finden.

Ich hatte ein ähnliches Problem in meiner app, nach einiger Untersuchung bemerkte ich, dass aus irgendeinem Grunde glibc nicht zurück Speicher an dem System, wenn zugeordneten Objekte klein sind (in meinem Fall weniger als 120 Byte).
Schauen Sie sich diesen Code:  

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

Programmausgang:

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

ca. 64 MB zurückkehren nicht auf System. Als ich geändert typedef: typedef x<110> X; Programm Ausgabe sieht wie folgt aus:

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

fast alle Speicher wurde befreit. Ich habe auch bemerkt, dass in jedem Fall mit malloc_trim(0) Speicher-System freigegeben.
Hier wird ausgegeben, nachdem oben auf den Code hinzufügen 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

Für all ‚normal‘ mallocs, einschließlich denen, die Sie erwähnt haben, wird der Speicher freigegeben von Ihrem Prozess wiederverwendet werden, aber nicht zurück auf das gesamte System. zurück auf das gesamte System Loslassen geschieht nur, wenn Sie schließlich beendet verarbeiten.

Von denen, die Sie auflisten, wird nur Hoard Speicher an das System zurückkehren ... aber wenn es tatsächlich tun kann, dass eine Menge auf dem Programm des Zuweisungsverhalten abhängen.

Die kurze Antwort: malloc Subsystem zu erzwingen Speicher OS zurückzukehren, verwenden Sie malloc_trim (). Andernfalls Verhalten der Rückkehr Speicher ist abhängig von der Implementierung.

FreeBSD 12 des malloc(3) verwendet jemalloc 5.1, die wieder freigegebenen Speicher ( "dirty Seiten"), um das Betriebssystem mit madvise(...MADV_FREE) .

Freed Speicher wird nur nach einer Zeitverzögerung wieder durch opt.dirty_decay_ms opt.muzzy_decay_ms und gesteuert wird; finden Sie in der Manpage und diese Ausgabe auf Verfall basierte ungenutzt schmutzige Seite Spülen , um weitere Informationen zu implementieren.

Frühere Versionen von FreeBSD ausgeliefert mit älteren Versionen von jemalloc, die auch Speicher freigegeben zurückkehren, sondern verwenden einen anderen Algorithmus, um zu entscheiden, was zu reinigen und wann.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top