最近看Dave Cheney的一篇文章,发现一个有趣的代码片段,里面展示了一个8byte的内存优化。
代码片段是这样的:
1 | func BenchmarkSortStrings(b *testing.B) { |
代码很简单,是对一个[]string
做排序的内存分配压测
其中
1 | var ss sort.StringSlice = s |
等同于代码
1 | sort.Strings(s) |
涉及了对 []string
转换为实现排序的接口 sort.Interface
了解iface
实现的同学知道其data
会存储底层数据,一般是一个机器字长的大小(8bytes
)
而slice
是24bytes
: 底层数组指针(8bytes
)+ 长度(8bytes
)+ 容量(8bytes
)
直接存不下,就只能indirection
, 存指向切片的指针了
创建前片指针的过程中,切片escape到了heap上,因为不知道原切片ss
是否会在si
使用过程中消失。
即,内存分配发生在了这里!
看下压测结果(go1.16
):
1 | $ go test sort_test.go -bench . -benchmem |
结果就是24bytes
啊,那所谓的8bytes
优化在哪里呢
是相对于的go1.16
前版本的go
的, 比如go1.15
下:
1 | $ go1.15 test sort_test.go -bench . -benchmem |
找了下具体提交,其实就是在内存分配里针对三个机器字大小增加了24bytes
的sizeClass
,避免原来的向上取整到32bytes
感兴趣的同学可以去看着具体实现:
runtime: add 24 byte allocation size class
题外话,好久没有更新了,不好意思了都,后边再捡起来😂
如有疑问,请文末留言交流或邮件:newbvirgil@gmail.com 本文链接 : https://newbmiao.github.io/2021/08/07/one-8-bytes-optimization.html