sync.Pool通过复用短生命周期对象减少内存分配和GC压力,适用于临时缓冲区、频繁创建的结构体等场景,使用时需重置对象状态并避免当作持久化缓存,结合pprof和基准测试可量化优化效果。

Golang中,要显著减少内存分配,特别是对于那些短生命周期、频繁创建和销毁的对象,
sync.Pool
sync.Pool
New
来看一个简单的例子,假设我们有一个
Buffer
package main
import (
"bytes"
"fmt"
"sync"
"time"
)
// 定义一个简单的Buffer类型
type Buffer struct {
bytes.Buffer
}
// 创建一个sync.Pool来存储Buffer对象
var bufferPool = sync.Pool{
New: func() interface{} {
// 当池中没有可用对象时,New方法会被调用来创建新对象
// 我个人习惯在这里预设一些容量,避免后续的内部扩容
return &Buffer{Buffer: *bytes.NewBuffer(make([]byte, 0, 1024))}
},
}
func main() {
// 模拟高并发下频繁使用Buffer的场景
for i := 0; i < 10; i++ {
go func(id int) {
// 从池中获取Buffer
buf := bufferPool.Get().(*Buffer)
// 确保使用完毕后将Buffer放回池中,并且重置其状态
defer func() {
buf.Reset() // 清空Buffer内容,但保留底层容量
bufferPool.Put(buf)
}()
// 使用Buffer
buf.WriteString(fmt.Sprintf("Hello from goroutine %d!", id))
fmt.Println(buf.String())
}(i)
}
time.Sleep(1 * time.Second) // 等待所有goroutine执行完毕
fmt.Println("Done.")
}
在这个例子里,
bufferPool.Get()
*Buffer
New
defer bufferPool.Put(buf)
*Buffer
buf.Reset()
立即学习“go语言免费学习笔记(深入)”;
在我看来,
sync.Pool
bytes.Buffer
至于适用场景,我通常会考虑以下几类:
[]byte
bytes.Buffer
sync.Pool
但它不是万能药。它不适合作为常规缓存,因为它池中的对象是可能在GC时被清除的,你不能指望它一直都在。它的设计初衷就是为了减少“临时性”对象的分配。
这块儿我踩过不少坑,所以有些心得想分享。
常见的误区:
sync.Pool
sync.Pool
Put
Get
Get
Put
Reset
bytes.Buffer
Reset
Put
Get
sync.Pool
sync.Pool
正确姿势:
sync.Pool
sync.Pool
Put
bytes.Buffer
Reset()
sync.Pool
sync.Pool
衡量
sync.Pool
pprof
pprof
heap
allocs
go tool pprof -http=:xxxx http://localhost:yyyy/debug/pprof/heap
go tool pprof -http=:xxxx http://localhost:yyyy/debug/pprof/allocs
sync.Pool
alloc_objects
alloc_space
alloc_objects
inuse_objects
inuse_space
sync.Pool
基准测试(Benchmark):
_test.go
go test -bench . -benchmem
sync.Pool
allocs/op
B/op
sync.Pool
allocs/op
B/op
除了
sync.Pool
make([]T, 0, capacity)
bytes.Buffer
strings.Builder
int8
int
GOGC
GOGC=50
以上就是如何减少Golang内存分配 sync.Pool对象池应用的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号