最近看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
本文链接 : 