带goroutine的Go程序内存占用过高,求内存复用方案及sync.Pool排查
问题分析与解决方案
一、当前sync.Pool实现的问题
- 语法错误:
pool.(Get).([]byte)是错误写法,正确应为pool.Get().([]byte);小写的pool.put应为大写的pool.Put - 切片索引逻辑错误:你直接用文件的offset作为切片的起始索引,切片索引是从0开始的,和文件偏移没有关系,该写法会直接导致数组越界panic,且读取的数据根本没有写入到正确的切片位置
- 内存复用逻辑无效:你从pool拿到的切片
d没有实际传给upload方法,代码里写的upload(data)的data变量未定义,相当于你还是在别处隐式申请内存存储上传数据,完全没有用到pool里的内存,所以内存占用没有改善 - 工具不匹配需求:
sync.Pool的设计目标是缓存临时对象,池内对象随时可能被GC回收,不符合你「不依赖GC、固定4块内存永久复用」的预期
二、符合需求的固定内存复用实现
你的需求是4个消费者goroutine各自绑定一块固定大小的内存,无需每次申请也不需要GC回收,直接在启动goroutine的时候预分配切片传入、全程复用即可:
const chunkSize = 16 << 20 // 16MB,可根据需求改为8/32MB type Block struct { offset int64 size int64 } func main() { consumerCount := 4 // 提前分配4块固定大小的内存,全程复用不会被GC回收 buffers := make([][]byte, consumerCount) for i := 0; i < consumerCount; i++ { buffers[i] = make([]byte, chunkSize) } // blocks是你预先生成的二维任务数组 for i := 0; i < consumerCount; i++ { go consumer(blocks[i], buffers[i]) } // 其他调度逻辑... } func consumer(blocks []Block, buf []byte) { // 循环处理任务,根据你自己的任务调度逻辑调整循环条件 for { currentWritePos := 0 totalSize := int64(0) // 先校验总大小不超过buf容量,避免越界 for _, block := range blocks { totalSize += block.size } if totalSize > chunkSize { // 处理分片超过上限的逻辑,比如拆分block } for _, block := range blocks { // 直接读取到复用的buf中,从当前写入位置开始写 n, err := file.ReadAt(buf[currentWritePos:currentWritePos+int(block.size)], block.offset) if err != nil { // 错误处理逻辑 } currentWritePos += n } // 上传buf中实际读取到的长度的数据 upload(buf[:currentWritePos]) // 不需要释放内存,下一轮循环直接覆盖buf即可 } }
如果需要多goroutine共享内存池、不需要和固定goroutine绑定,可以用带缓冲的channel实现更可控的固定内存池,同样不会被GC回收:
var bufPool chan []byte const chunkSize = 16 << 20 const poolSize = 4 func init() { bufPool = make(chan []byte, poolSize) for i := 0; i < poolSize; i++ { bufPool <- make([]byte, chunkSize) } } func consumer(blocks []Block) { buf := <- bufPool // 从池里取内存 defer func() { bufPool <- buf }() // 用完放回池里,不会被GC回收 currentWritePos := 0 for _, block := range blocks { n, _ := file.ReadAt(buf[currentWritePos:currentWritePos+int(block.size)], block.offset) currentWritePos += n } upload(buf[:currentWritePos]) }
内容的提问来源于stack exchange,提问作者user2912611
相关产品推荐
相关产品推荐

