Golang 数据结构性能优化实践
仅仅通过对 struct 字段重新排序,优化内存对齐方式,就可以获得明显的内存和执行效率提升。原文: How to Speed Up Your Struct in Golang

如果你有 Golang 开发经验,一定定义过 struct 类型。
但可能你不知道,通过简单的重新排序 struct 字段,可以极大提高 Go 程序的速度和内存使用效率!
是不是难以置信?我们一起来看一下吧!
简单 Demo
在上面的代码片段中,我们创建了两个具有相同字段的结构体。然后编写一个简单程序分别输出其内存使用情况。
如你所见,它们在内存使用方面并不一样。
是什么原因导致两个完全相似的 struct 消耗的内存不同?
答案在于数据在计算机内存中的排列方式。
简而言之,数据结构对齐。
数据结构对齐

CPU 以字(word)为单位读取数据,而不是字节(byte)。
64 位系统中,一个 word 是 8 个字节,而 32 位系统中,一个 word 是 4 个字节。
简而言之,CPU 以其字长的倍数读取内存地址。

想象一下,在 64 位系统中,为了获取变量passportNum
,CPU 需要两个周期来访问数据。
第一个周期将获取内存的 0 到 7 字节,下一个周期获取其余内存字节。
把它想象成一个笔记本,每页只能存储一个字大小的数据(在本例中为 8 字节)。如果passportNum
分散在两个页,则需要两次读取才能检索到完整的数据。
非常低效。
因此需要数据结构对齐,让计算机将数据存储在等于数据大小倍数的地址上。

例如,2 字节数据可以存储在内存 0、2 或 4 中,而 4 字节数据可以存储在内存 0、4 或 8 中。

通过简单的对齐数据,计算机确保可以在一个 CPU 周期内检索到变量passportNum
。
数据结构填充

填充是实现数据对齐的关键。
计算机通过在数据结构之间填充额外的字节,从而对齐字段。
这就是额外内存的来源!
我们来回顾一下BadStruct
和GoodStruct
。

GoodStruct
消耗更少的内存,仅仅因为与BadStruct
相比,其 struct 字段顺序更合理。
由于填充,两个 13 字节的数据结构分别变成了 16 字节和 24 字节。
因此,可以仅仅通过对 struct 字段重新排序来节省额外的内存!
这种优化为什么重要?
问题来了,你为什么要关心这个?
两个方面,速度和内存使用。
我们做一个简单的基准测试来证明!
对GoodStruct
和BadStruct
进行基准测试的方法是循环遍历数组,并将 struct 字段累加到变量中。

从结果中可以看出,遍历GoodStruct
确实比BadStruct
花费时间更少。
对 struct 字段重排序可以优化应用程序的内存使用和速度。
想象一下,维护一个具有大量结构体的大型应用程序,改变将会更为明显。
结语
好了,全文到此为止,我们以一个简单的行动呼吁来结束:
一定要对 struct 结构字段进行重排序!
你好,我是俞凡,在 Motorola 做过研发,现在在 Mavenir 做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI 等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。为了方便大家以后能第一时间看到文章,请朋友们关注公众号"DeepNoMind",并设个星标吧,如果能一键三连(转发、点赞、在看),则能给我带来更多的支持和动力,激励我持续写下去,和大家共同成长进步!
版权声明: 本文为 InfoQ 作者【俞凡】的原创文章。
原文链接:【http://xie.infoq.cn/article/34f06f97487a73b6c75501103】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论