No se puede liberar memoria una vez ocupada por bytes.Buffer

Recibo bytes de texto ASCII comprimido en bytes compressedbytes de tipo [] byte. El problema al que me enfrento es que el siguiente procedimiento ocupa una gran cantidad de memoria que no se libera una vez que la función llega a su fin y permanece ocupada durante todo el tiempo de ejecución del progtwig.

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

Me di cuenta de que el tipo en uso es bytes.Buffer y este tipo tiene las funciones Reset() y Truncate() , pero ninguna de ellas permite liberar la memoria que está ocupada.

La documentación de Reset() indica lo siguiente:

Restablecer restablece el búfer para que esté vacío, pero conserva el almacenamiento subyacente para su uso en futuras escrituras. Restablecer es lo mismo que Truncar (0).

¿Cómo puedo desarmar el buffer y liberar la memoria nuevamente? Mi progtwig necesita aproximadamente 50 MB de memoria durante la ejecución que dura 2 horas. Cuando importo cadenas comprimidas zlib, el progtwig necesita 200 MB de memoria.

Gracias por tu ayuda.

=== Actualización

Incluso creé una función separada para la descompresión y llamé al recolector de basura manualmente con runtime.GC() después de que el progtwig regrese de esa función sin éxito.

 // unpack decompresses zlib compressed bytes func unpack(packedData []byte) []byte { b := bytes.NewReader(packedData) r, err := zlib.NewReader(b) if err != nil { panic(err) } cleartext, err := ioutil.ReadAll(r) if err != nil { panic(err) } r.Close() return cleartext } 

Algunas cosas para limpiar. Go es un lenguaje recogido de basura, lo que significa que la memoria asignada y utilizada por las variables se libera automáticamente por el recolector de basura cuando esas variables se vuelven inalcanzables (si tiene otro puntero a la variable, que aún cuenta como “alcanzable”).

La memoria liberada no significa que se devuelve al sistema operativo. La memoria liberada significa que la memoria puede recuperarse, reutilizarse para otra variable si es necesario. Por lo tanto, desde el sistema operativo no verá que la memoria disminuya de inmediato solo porque alguna variable se volvió inalcanzable y el recolector de basura la detectó y liberó la memoria utilizada por ella.

Sin embargo, el tiempo de ejecución de Go devolverá la memoria al sistema operativo si no se utiliza durante un tiempo (que generalmente es de alrededor de 5 minutos). Si el uso de la memoria aumenta durante este período (y opcionalmente se reduce de nuevo), la memoria probablemente no se devuelva al sistema operativo.

Si esperas un tiempo y no vuelves a asignar memoria, la memoria liberada se devolverá al sistema operativo (obviamente no todos, pero los “trozos grandes” no utilizados serán). Si no puede esperar a que esto suceda, puede llamar a debug.FreeOSMemory() para forzar este comportamiento:

FreeOSMemory fuerza una recolección de basura seguida de un bash de devolver tanta memoria al sistema operativo como sea posible. (Incluso si no se llama, el tiempo de ejecución devuelve gradualmente la memoria al sistema operativo en una tarea en segundo plano).

Mira este tipo de pregunta + respuestas antiguas pero realmente informativas:

Go 1.3 Garbage collector no libera la memoria del servidor de vuelta al sistema

Eventualmente se lanzará cuando ya nada lo haga referencia, Go tiene un GC bastante decente.