开门见山,今天给大家分享通过简单地重新排序结构体中的字段,极大地提高 Go 程序的速度和内存使用率的方法~
01
【数据结构对齐】
【举个栗子】
在上面的例子中,我们定义了两个具有相同字段的结构体。接下来让我们编写一个简单的程序来输出他们的内存使用情况。
【结果如下】
通过上面我们可以发现它们占用的内存不同。到底发生了什么,导致两个字段相同的结构体消耗不同的字节?
答案是数据在操作系统中的内存排列方式,也可以说是数据结构对齐。
02
【原理介绍】
CPU 以字长的方式读取数据,64 位操作系统中一个字长为 8 个字节,而 32 位操作系统中一个字长为 4 个字节。换句话说,CPU 以字长的倍数读取地址。
在 64 位操作系统中,为了获取变量 IdCardNumber,我们的 CPU 需要两个周期来访问数据,而不是一个周期。
第一个周期将获取到 0 到 7 的内存,其余周期获取其余部分。
把它想象成一个笔记本,每页只能存储一个字大小的数据,此时是 8 个字节。如果 IdCardNumber 分散在两个页面上,则需要翻页两次才能检索完整的数据。
但这是低效的
因此我们需要对齐数据结构,将数据存储在一个地址等于数据大小的倍数的位置。
例如,一个 2 字节的数据可以存储在内存 0、2 或 4 中,而一个 4 字节的数据可以存储在内存 0、4 或 8 中。
通过简单的对齐数据,确保 IdCardNumber 可以在同一个 CPU 周期内检索到变量。
填充是实现数据对齐的关键。操作系统在数据结构之间用额外的字节填充数据以对齐它们。这就是额外内存的来源!
让我们再来看一看 BadStruct 和 GoodStruct。
GoodStruct 消耗更少的内存,仅仅是因为它比 BadStruct 有更好的结构体字段顺序。
由于填充,两个数据结构分别变成了 16 字节和 24 字节。所以,只需重新排序结构体中的字段,就可以节省额外的内存!
最后,我们来做一个简单的基准测试来证明它在速度和内存的区别。
【结果如下】
从结果可以看出,遍历 GoodStruct 花费的时间确实更少。重新排序结构体字段可以提高程序的内存使用率和速度。
了解了简单的数据对齐技术,快来重新排序结构体中你的字段吧!
阅读原文
了解老九学堂暑期线下就业班详情