Golang
主页 > 脚本 > Golang >

GoLang sync.Pool简介与用法

2023-10-11 | 佚名 | 点击:

一句话总结:保存和复用临时对象,减少内存分配,降低GC压力

sync.Pool是可伸缩的,也是并发安全的,其大小仅受限于内存大小。sync.Pool用于存储那些被分配了但是没有使用,而未来可能会使用的值。这样就可以不用再次经过内存分配,可直接复用已有对象,减轻GC的压力,从而提升系统性能。

使用方法

声明对象池

1

2

3

4

5

6

7

8

9

10

11

12

type Student struct {

   Name   string

   Age    int32

   Remark [1024]byte

}

func main() {

   var studentPool = sync.Pool{

      New: func() interface{} {

         return new(Student)

      },

   }

}

Get & Put

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

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)

}

性能测试

以下是性能测试的代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

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进行性能优化!

原文链接:
相关文章
最新更新