首頁 > 軟體

GoLang sync.Pool簡介與用法

2023-01-04 14:00:03

使用場景

一句話總結:儲存和複用臨時物件,減少記憶體分配,降低GC壓力

sync.Pool是可伸縮的,也是並行安全的,其大小僅受限於記憶體大小。sync.Pool用於儲存那些被分配了但是沒有使用,而未來可能會使用的值。這樣就可以不用再次經過記憶體分配,可直接複用已有物件,減輕GC的壓力,從而提升系統效能。

使用方法

宣告物件池

type Student struct {
   Name   string
   Age    int32
   Remark [1024]byte
}
func main() {
   var studentPool = sync.Pool{
      New: func() interface{} {
         return new(Student)
      },
   }
}

Get & Put

type Student struct {
   Name   string
   Age    int32
   Remark [1024]byte
}
var buf, _ = json.Marshal(Student{Name: "lxy", Age: 18})
func Unmarsh() {
   var studentPool = sync.Pool{
      New: func() interface{} {
         return new(Student)
      },
   }
   stu := studentPool.Get().(*Student)
   err := json.Unmarshal(buf, stu)
   if err != nil {
      return
   }
   studentPool.Put(stu)
}
  • Get()用於從物件池中獲取物件,因為返回值是interface{},因此需要型別轉換
  • Put()則是在物件使用完畢之後,返回物件池

效能測試

以下是效能測試的程式碼:

package benchmem
import (
   "encoding/json"
   "sync"
   "testing"
)
type Student struct {
   Name   string
   Age    int32
   Remark [1024]byte
}
var buf, _ = json.Marshal(Student{Name: "lxy", Age: 18})
var studentPool = sync.Pool{
   New: func() interface{} {
      return new(Student)
   },
}
func BenchmarkUnmarshal(b *testing.B) {
   for n := 0; n < b.N; n++ {
      stu := &Student{}
      json.Unmarshal(buf, stu)
   }
}
func BenchmarkUnmarshalWithPool(b *testing.B) {
   for n := 0; n < b.N; n++ {
      stu := studentPool.Get().(*Student)
      json.Unmarshal(buf, stu)
      studentPool.Put(stu)
   }
}

輸入以下命令:

 go test -bench . -benchmem

以下是效能測試的結果:

goos: windows
goarch: amd64                                      
pkg: ginTest                                       
cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz
BenchmarkUnmarshal-8               17004             74103 ns/op            1392 B/op          8 allocs/op
BenchmarkUnmarshalWithPool-8       17001             71173 ns/op             240 B/op          7 allocs/op
PASS
ok      ginTest 3.923s

在這個例子中,因為 Student 結構體記憶體佔用較小,記憶體分配幾乎不耗時間。而標準庫 json 反序列化時利用了反射,效率是比較低的,佔據了大部分時間,因此兩種方式最終的執行時間幾乎沒什麼變化。但是記憶體佔用差了一個數量級,使用了 sync.Pool 後,記憶體佔用僅為未使用的 240/1392 = 1/6,對 GC 的影響就很大了。

我們甚至在fmt.Printf的原始碼裡面也使用了sync.Pool進行效能優化!

到此這篇關於GoLang sync.Pool簡介與用法的文章就介紹到這了,更多相關GoLang sync.Pool內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com