我正在
sql/driver
中实现 Rows 接口。在实现Next(dest []Value) error
方法时,我发现当数据结果非常大时,堆分配会成为性能瓶颈。我做了一个测试来说明这一点。
b := binary.LittleEndian.AppendUint32(nil, 0)
b = binary.LittleEndian.AppendUint16(b, 5)
b = append(b, "hello"...)
t := time.Now()
var v driver.Value
for i := 0; i < 100000000; i++ {
v = b[5:11]
}
_ = v
fmt.Println(time.Since(t))
打印执行时间4.154244695s。 CPU pprof pprof 结果显示,在
runtime.mallocgc
上花费了太多时间,因为 v = b[5:11]
需要在堆中分配切片头。
我想知道是否有办法减少堆分配带来的性能瓶颈。或者有什么其他方法可以绕过吗?
b[5:11]
的值是一个切片,由一个指针和两个整数表示。
接口 当值无法放入单个单词时,会在堆上分配值的副本,而切片则不然。
那么
s := b[5:11]
很便宜但是
var v any = s
需要分配内存。恐怕除了依赖 Go 内部之外没有其他办法解决这个问题。