2016-05-23 7 views
2

Ich erhalte Bytes komprimierten ASCII-Text in compressedbytes vom Typ [] Byte. Das Problem, dem ich gegenüberstehe, ist, dass die folgende Prozedur viel Speicher belegt, der nicht freigegeben wird, nachdem die Funktion ihr Ende erreicht hat und während der gesamten Laufzeit des Programms belegt bleibt.Speicher kann nicht einmal durch Bytes belegt werden.Buffer

b := bytes.NewReader(compressedbytes) 
    r, err := zlib.NewReader(b) 
    if err != nil { 
     panic(err) 
    } 
    cleartext, err = ioutil.ReadAll(r) 
    if err != nil { 
     panic(err) 
    } 

bemerkte ich, dass die Art in Gebrauch ist bytes.Buffer und diese Art hat die Reset() und Truncate() Funktionen, aber keiner von ihnen ermöglicht, den Speicher freizugeben, die einmal besetzt ist.

Die documentation von Reset() besagt Folgendes:

Zurücksetzen Damit wird der Puffer leer sein, aber es behält den zugrunde liegenden Speicher für die Nutzung durch zukünftige schreibt. Zurücksetzen ist dasselbe wie Abschneiden (0).

Wie kann ich den Puffer aufheben und den Speicher wieder freigeben? Mein Programm benötigt ca. 50 MB Arbeitsspeicher während des Laufs, der 2 Stunden dauert. Wenn ich Zeichenfolgen importiere, die zlib komprimiert sind, benötigt das Programm 200 MB Speicher.

Danke für Ihre Hilfe.

=== Update-

Ich habe sogar eine eigene Funktion für die Dekompression und der Garbage Collector mit runtime.GC() nach kehrt das Programm von dieser Funktion ohne Erfolg manuell aufrufen.

+0

Was den Puffer mit b.WriteTo (os.stdout Trockenlegung)? – khrm

+1

Wie messen Sie die Speichernutzung? – elithrar

+0

Ich habe vor und nach dieser Anweisung eine Pause eingelegt (warten auf Benutzereingaben) und beobachten, wie der Prozessspeicher dazwischen wächst. Ich überprüfe es in SysInternals ProcessExplorer in Spalte "WorkingSetSize" und "PrivateBytes". – JohnGalt

Antwort

17

Einige Dinge zu klären. Go ist eine Garbage Collection-Sprache, was bedeutet, dass Speicher, der von Variablen zugewiesen und verwendet wird, automatisch vom Garbage Collector freigegeben wird, wenn diese Variablen nicht erreichbar sind (wenn Sie einen anderen Zeiger auf die Variable haben, der immer noch als "erreichbar" gilt).

Freigegebener Speicher bedeutet nicht, dass es an das Betriebssystem zurückgegeben wird. Freigegebener Speicher bedeutet, dass der Speicher zurückgewonnen werden kann, wenn eine Notwendigkeit für eine andere Variable besteht. Sie werden also vom Betriebssystem aus keinen sofortigen Speicherverlust sehen, nur weil eine Variable nicht erreichbar war und der Garbage Collector dies erkannt und den von ihm verwendeten Speicher freigegeben hat.

Die Go-Laufzeit wird jedoch Speicher an das Betriebssystem zurückgeben, wenn es einige Zeit nicht verwendet wird (was normalerweise etwa 5 Minuten dauert). Wenn die Speicherauslastung während dieses Zeitraums zunimmt (und optional erneut verkleinert wird), wird der Speicher höchstwahrscheinlich nicht an das Betriebssystem zurückgegeben.

Wenn Sie einige Zeit warten und nicht wieder Speicher reservieren, wird freigegebener Speicher schließlich an das Betriebssystem zurückgegeben (offensichtlich nicht alle, aber unbenutzte "große Brocken" sein). Wenn Sie nicht warten kann passieren, können Sie debug.FreeOSMemory() nennen dieses Verhalten zu erzwingen:

FreeOSMemory erzwingt eine Garbage Collection durch einen Versuch gefolgt, wie viel Speicher für das Betriebssystem wie möglich zurückzukehren. (Auch wenn dies nicht aufgerufen wird, gibt die Laufzeit in einer Hintergrundaufgabe schrittweise Speicher an das Betriebssystem zurück.

)

Schauen Sie sich diese Art von alten, aber sehr informativ Frage + Antwort:

Go 1.3 Garbage collector not releasing server memory back to system

+0

Vielen Dank - das hat geholfen – JohnGalt

2

Es wird schließlich freigegeben, wenn nichts mehr darauf verweist, Go hat einen ziemlich guten GC.

+0

Ich legte sogar alles in eine separate Funktion, rufen Sie den Garbage Collector nach der Rückkehr von der Funktion von runtime.GC() und es wird nicht von der Garbage Collector aufgeräumt – JohnGalt

+0

@JohnGalt: Es ist nicht die Garbage Collectors Aufgabe, Speicher freizugeben. Der Heap-Scavenger kann dem Betriebssystem bei der Ausführung freien Speicher zurückgeben, aber das hat nichts mit GC zu tun. – JimB