GoLang sync.Pool簡介與用法

使用場景

一句話總結:保存和復用臨時對象,減少內存分配,降低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內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: