sync.Pool a été introduit en Go pour réutiliser des objets temporaires et réduire la pression sur le ramasse-miettes. Historiquement, les développeurs créaient leurs propres pools d'objets en utilisant des mutexes, ce qui entraînait un code complexe et des erreurs potentielles de synchronisation. sync.Pool est une structure thread-safe de la bibliothèque standard, destinée à produire un objet lors de la première utilisation, à le stocker et à le retourner ensuite dans le pool pour une réutilisation.
Le problème — avec un grand nombre d'objets à courte durée de vie (par exemple, des tampons dans un serveur HTTP), le système passe souvent beaucoup de temps sur les allocations. L'utilisation de sync.Pool permet de mettre en cache des objets facultativement, sans garantir leur conservation en mémoire, mais en améliorant les performances grâce à une réduction du nombre de collectes de déchets.
La solution — utiliser Pool pour des structures temporaires, homogènes, à utilisation rapide (par exemple, bytes.Buffer), en retournant l'objet dans le pool avec la méthode Put et en l'extrayant avec Get. Les objets peuvent être supprimés du pool à tout moment (par exemple, lors du lancement de GC), ce qui ne convient pas pour le stockage à long terme.
Exemple de code :
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) // il est nécessaire de le retourner }
Caractéristiques clés :
sync.Pool peut-il être utilisé pour le stockage à long terme d'état ?
Non, tout objet dans le Pool peut être supprimé par le système à tout moment (lors de GC ou d'une réduction de charge). Pool est destiné uniquement au stockage temporaire entre goroutines.
Le Pool garantit-il le retour du même objet qui a été précédemment placé ?
Non. Le Pool retourne tout objet approprié ou en crée un nouveau si nécessaire. Il ne faut pas établir de lien entre l'utilisateur et l'objet du Pool.
Faut-il nettoyer/réinitialiser l'objet avant de le retourner dans le Pool ?
Oui, sinon le prochain thread pourrait obtenir un objet "sale" avec des restes de données précédentes.
Cas négatif
Le développeur conserve dans le Pool des états de clients pour reconnecter au chat. Après le démarrage de GC, les connexions disparaissent et les utilisateurs perdent leurs données.
Avantages :
Inconvénients :
Cas positif
Les objets Buffer pour marshal/unmarshal JSON sont placés dans le Pool et utilisés pour le traitement par lots des messages. Après traitement, les objets sont nettoyés et retournés dans le pool, réduisant le nombre d'allocations.
Avantages :
Inconvénients :