用goroutines修复go程序的内存消耗



我正在处理一个涉及生产者-消费者模式的问题。我有一个生产者负责生产任务,而消费者负责消耗任务。使用者的任务是从文件中读取一些数据,然后将这些数据上传到S3。一个消费者可以读取高达xMB(8/16/32(的数据,然后将其上传到s3。将所有数据保留在内存中会导致内存消耗超过程序的预期,所以我改为从文件中读取数据,然后将其写入某个临时文件,然后将文件上传到S3,尽管这在内存方面表现更好,但CPU受到了打击。我想知道是否有任何方法可以分配一次固定大小的内存,然后在不同的goroutine之间使用它?我想要的是,如果我有4个goroutine,那么我可以分配4个不同的xMB数组,然后在每个goroutine调用中使用相同的数组,这样goroutine就不会每次都分配内存,也不会依赖GC来释放内存?

编辑:添加我的代码的关键。我的首选消费者看起来像:

type struct Block {
offset int64
size int64
}
func consumer (blocks []Block) {
var dataArr []byte
for _, block := range blocks {
data := file.Read(block.offset, block.size)
dataArr = append(dataArr, data)
}
upload(dataArr)  
}

我从基于块的文件中读取数据,这个块可以包含几个受xMB限制的小块或一个xMB的大块。

第2版:已尝试同步。基于评论中的建议的池。但我没有看到内存消耗有任何改善。我做错什么了吗?

var pool *sync.Pool
func main() {
pool = &sync.Pool{
New: func()interface{} {
return make([]byte, 16777216)
},
}
for i:=0; i < 4; i++ {
// blocks is 2-d array each index contains array of blocks.
go consumer(blocks[i])
}

}

go consumer(blocks []Blocks) {
var dataArr []byte
d := pool.(Get).([]byte)
for _, block := range blocks {
file.Read(block.offset,block.size,d[block.offset:block.size])
}
upload(data)  
pool.put(data)
}

看看StaticCheck的SA6002,关于sync.Pool。您也可以使用pprof工具。