Object Pooling with sync.Pool
sync.Pool bilan obyektlarni qayta ishlatish
Restoranda har bir mijoz uchun yangi likopcha sotib olish o'rniga, ishlatilgan likopchalarni yuvib, qayta ishlatasiz. Bu — vaqt va resursni tejaydi. Object Pool naqshi — dasturda ham xuddi shunday: tez-tez yaratiladigan va tashlanadigan obyektlarni (masalan katta bufer) har safar noldan yaratish o'rniga, ishlatilganidan keyin "yuvib", qayta berish uchun saqlab qo'yish.
Go'da bu maqsad uchun sync.Pool mavjud. U ayniqsa xotira ajratish (allocation) qimmatga tushadigan holatlarda foydali — masalan, katta hajmdagi vaqtinchalik buferlar bilan tez-tez ishlaydigan serverlarda.
package main
import (
"fmt"
"sync"
)
type Buffer struct {
data []byte
}
var pool = sync.Pool{
New: func() interface{} {
return &Buffer{data: make([]byte, 0, 1024)}
},
}
func main() {
buf := pool.Get().(*Buffer)
buf.data = append(buf.data, []byte("salom")...)
fmt.Println(string(buf.data))
buf.data = buf.data[:0] // "tozalash" — foydalanishdan oldin bo'shatib qo'yish
pool.Put(buf)
buf2 := pool.Get().(*Buffer)
fmt.Println(len(buf2.data)) // bo'sh, lekin xotira allaqachon ajratilgan
}sync.Pool{New: ...} — agar to'plamda hozircha bo'sh (ishlatilmayotgan) obyekt bo'lmasa, New funksiyasi chaqirilib, yangisi yaratiladi. pool.Get() — to'plamdan bitta obyekt oladi (yo eski, yo yangi). pool.Put(buf) — ishlatib bo'lgach, obyektni qaytarib, keyingi safar boshqa kimdir foydalanishi uchun to'plamga qo'shadi.
Muhim ogohlantirish: Putdan oldin obyektni albatta "tozalash" kerak (bu yerda buf.data[:0] bilan uzunlikni nolga tushirish) — aks holda keyingi olguvchi eski, kutilmagan ma'lumotni ko'rishi mumkin. Va yana bir narsa: sync.Pooldagi obyektlar kafolatlanmagan — Go'ning axlat yig'uvchisi (garbage collector) istalgan vaqtda to'plamni bo'shatib yuborishi mumkin, shuning uchun sync.Poolni faqat vaqtinchalik, tez-tez qayta yaratiladigan obyektlar uchun ishlating, doimiy saqlash uchun emas.
>_ Exercise
sync.Pool yordamida qayta ishlatiladigan hisoblagich obyektini yasang.
- •Counter struct'i (Value int) yasang
- •sync.Pool yarating: New funksiyasi &Counter{} qaytarsin
- •pool.Get() bilan Counter oling, Value'ni 5 ga o'rnating, chop eting
- •Value'ni 0 ga qaytarib, pool.Put() bilan qaytaring, so'ng yana Get() qilib Value'ni chop eting
Stuck? Reveal a hint to help you.
Key Takeaway
Key Takeaway:
sync.Pool tez-tez yaratilib-tashlanadigan obyektlarni qayta ishlatib, xotira ajratish yukini kamaytiradi — lekin obyektni qaytarishdan oldin uni "tozalash" dasturchining o'z zimmasida.
NEXT UP
Singleflight Pattern
$ go run main.go
Kodingizni ishga tushiring