sync.Pool è stato introdotto in Go per il riutilizzo di oggetti temporanei e per ridurre la pressione sul garbage collector. Storicamente, gli sviluppatori creavano i propri pool di oggetti utilizzando mutex, ma questo portava a un codice complesso e a possibili errori di sincronizzazione. sync.Pool è una struttura thread-safe della libreria standard, destinata alla produzione di oggetti alla prima richiesta, alla memorizzazione e al successivo restituzione di questo oggetto nel pool per il riutilizzo.
Il problema è che, con un gran numero di oggetti di breve durata (ad esempio, buffer in un server HTTP), il sistema spesso impiega molto tempo per le allocazioni. L'uso di sync.Pool consente di memorizzare facoltativamente oggetti in cache, senza garantire la loro persistenza in memoria, ma aumentando le prestazioni grazie alla riduzione del numero di garbage collection.
La soluzione consiste nell'utilizzare il Pool per strutture temporanee, omogenee e a rapido utilizzo (ad esempio, bytes.Buffer), restituendo l'oggetto nel pool tramite il metodo Put e estraendolo tramite Get. Gli oggetti possono essere rimossi dal pool in qualsiasi momento (ad esempio, all'avvio del GC), quindi non è adatto per la memorizzazione a lungo termine.
Esempio di codice:
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) // è obbligatorio restituire }
Caratteristiche principali:
Può sync.Pool essere utilizzato per la memorizzazione a lungo termine dello stato?
No, qualsiasi oggetto nel Pool può essere rimosso dal sistema in qualsiasi momento (durante il GC o con una riduzione del carico). Il Pool è destinato solo per la memorizzazione temporanea tra goroutine.
Garantisce il Pool il ritorno dello stesso oggetto che era stato precedentemente messo?
No. Il Pool restituisce qualsiasi oggetto idoneo o ne crea uno nuovo, se necessario. Non dovrebbe essere mantenuta alcuna associazione tra l'utente e l'oggetto del Pool.
È necessario pulire/resetare l'oggetto prima di restituirlo al Pool?
Sì, altrimenti il thread successivo potrebbe ricevere un oggetto "sporco" con residui di dati precedenti.
Casi negativi
Un sviluppatore memorizza nello Pool lo stato dei clienti per riconnettersi alla chat. Dopo l'avvio del GC le connessioni scompaiono e gli utenti perdono dati.
Vantaggi:
Svantaggi:
Casi positivi
Gli oggetti Buffer per marshal/unmarshal JSON vengono memorizzati nel Pool e utilizzati per l'elaborazione batch dei messaggi. Dopo l'elaborazione, gli oggetti vengono puliti e restituiti al pool, riducendo il numero di allocazioni.
Vantaggi:
Svantaggi: