sync.Pool został wprowadzony w Go w celu ponownego wykorzystania tymczasowych obiektów i zmniejszenia obciążenia dla zbieracza śmieci. Historycznie programiści tworzyli własne puli obiektów, używając mutexów, co prowadziło do skomplikowanego kodu i możliwych błędów synchronizacji. sync.Pool jest bezpieczną wątkowo strukturą z biblioteki standardowej, zaprojektowaną do generowania obiektu przy pierwszym dostępie, przechowywania i następnego zwracania tego obiektu do puli do ponownego wykorzystania.
Problem polega na tym, że przy dużej liczbie krótkożyjących obiektów (na przykład buforach w serwerze HTTP) system często spędza dużo czasu na alokacjach. Użycie sync.Pool pozwala opcjonalnie buforować obiekty, nie gwarantując ich zachowania w pamięci, ale zwiększając wydajność poprzez zmniejszenie liczby zbierania śmieci.
Rozwiązanie polega na używaniu Pool dla tymczasowych, jednorodnych, często używanych struktur (na przykład bytes.Buffer), zwracając obiekt do puli metodą Put i wydobywając przez Get. Obiekty mogą być usuwane z puli w dowolnym momencie (na przykład podczas uruchamiania GC), dlatego nie nadaje się do długotrwałego przechowywania.
Przykład kodu:
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) // konieczne jest zwrócenie }
Kluczowe cechy:
Czy sync.Pool może być używany do długoterminowego przechowywania stanu?
Nie, jakiekolwiek obiekty w Pool mogą być usunięte przez system w dowolnym momencie (przy GC lub zmniejszeniu obciążenia). Pool jest przeznaczony tylko do tymczasowego przechowywania między goroutine.
Czy Pool gwarantuje zwrócenie tego samego obiektu, który wcześniej został umieszczony?
Nie. Pool zwraca dowolny odpowiedni obiekt lub tworzy nowy w razie potrzeby. Nie należy przechowywać powiązania między użytkownikiem a obiektem Pool.
Czy należy czyścić/resetować obiekt przed zwrotem do Pool?
Tak, w przeciwnym razie kolejny wątek może otrzymać „brudny” obiekt z pozostałościami po wcześniejszych danych.
Negatywny przypadek
Programista przechowuje w Pool stany klientów do ponownego połączenia z czatem. Po uruchomieniu GC połączenia znikają, użytkownicy tracą dane.
Zalety:
Wady:
Pozytywny przypadek
Obiekty buforowe dla marshal/unmarshal JSON trafiają do Pool i są używane do przetwarzania wsadowego wiadomości. Po przetworzeniu obiekty są czyszczone i zwracane do puli, co zmniejsza liczbę alokacji.
Zalety:
Wady: