sync.Pool fue introducido en Go para reutilizar objetos temporales y reducir la presión sobre el recolector de basura. Históricamente, los desarrolladores creaban sus propios grupos de objetos utilizando mutexes, pero esto conducía a un código complejo y posibles errores de sincronización. sync.Pool es una estructura segura para hilos de la biblioteca estándar, diseñada para producir un objeto en la primera llamada, almacenar y luego devolver ese objeto al grupo para reutilización.
El problema es que, con un gran número de objetos de corta duración (por ejemplo, búferes en un servidor HTTP), el sistema a menudo gasta mucho tiempo en asignaciones. El uso de sync.Pool permite opcionalmente almacenar en caché los objetos, sin garantizar su conservación en memoria, pero aumentando el rendimiento al reducir el número de recolecciones de basura.
La solución es usar Pool para estructuras temporales, homogéneas y de uso rápido (por ejemplo, bytes.Buffer), devolviendo el objeto al grupo mediante el método Put y extrayéndolo a través de Get. Los objetos pueden ser eliminados del grupo en cualquier momento (por ejemplo, durante la ejecución de GC), por lo que no sirve para almacenamiento a largo plazo.
Ejemplo de código:
import ( "sync" "bytes" "fmt" ) var bufPool = sync.Pool{ New: func() interface{} { return new(bytes.Buffer) }, } func main() { b := bufPool.Get().(*bytes.Buffer) b.Reset() b.WriteString("hello, world!") fmt.Println(b.String()) bufPool.Put(b) // necesariamente retornamos }
Características clave:
¿Puede sync.Pool ser utilizado para almacenamiento a largo plazo?
No, cualquier objeto en el Pool puede ser eliminado por el sistema en cualquier momento (durante GC o disminución de carga). Pool está destinado únicamente al almacenamiento temporal entre goroutines.
¿Garantiza Pool la devolución del mismo objeto que fue insertado anteriormente?
No. Pool devuelve cualquier objeto adecuado o crea uno nuevo si es necesario. No se debe mantener una relación entre el usuario y el objeto de Pool.
¿Es necesario limpiar/resetear el objeto antes de devolverlo al Pool?
Sí, de lo contrario, el siguiente hilo puede recibir un objeto "sucio" con restos de datos anteriores.
Caso negativo
Un desarrollador guarda en Pool los estados de los clientes para reconexión al chat. Después de que se ejecuta GC, las conexiones desaparecen y los usuarios pierden datos.
Ventajas:
Desventajas:
Caso positivo
Se almacenan objetos Buffer para marshal/unmarshal JSON en el Pool y se utilizan para el procesamiento por lotes de mensajes. Después del procesamiento, los objetos se limpian y se devuelven al grupo, reduciendo el número de asignaciones.
Ventajas:
Desventajas: