在 golang 中优化数据结构/字对齐填充
Posted
技术标签:
【中文标题】在 golang 中优化数据结构/字对齐填充【英文标题】:Optimising datastructure/word alignment padding in golang 【发布时间】:2016-12-28 01:26:51 【问题描述】:与我在 C++ 中学到的类似,我相信填充会导致两个结构的实例大小不同。
type Foo struct
w byte //1 byte
x byte //1 byte
y uint64 //8 bytes
type Bar struct
x byte //1 byte
y uint64 //8 bytes
w byte// 1 byte
func main()
fmt.Println(runtime.GOARCH)
newFoo := new(Foo)
fmt.Println(unsafe.Sizeof(*newFoo))
newBar := new(Bar)
fmt.Println(unsafe.Sizeof(*newBar))
输出:
amd64
16
24
在定义结构成员时是否有经验法则可以遵循? (如类型大小的升序/降序)
是否有我们可以通过的编译时优化,可以自动解决这个问题?
或者我根本不应该担心这个?
【问题讨论】:
我做了一个例子,可以提供一些见解play.golang.org/p/dNWspo2Dxv 【参考方案1】:或者我根本不应该担心这个?
是的,你应该这样做。 这也称为mechanical sympathy(参见Go Time podcast episode),因此它还取决于您正在编译的硬件架构。
如图所示:
“The day byte alignment came back to bite me”(2014 年 1 月) “On the memory alignment of Go slice values”(2016 年 7 月)Go 切片中的值是 16 字节对齐的。它们不是 32 字节对齐的。 Go 指针是字节对齐的。
【讨论】:
我也尝试修复 2014 链接,但站点 kernel-panic.runkite.com 似乎消失了。 @ArnaudP 感谢您的编辑。我也恢复了 kernel-panic.runkite.com 链接。【参考方案2】:这取决于您正在开发的应用程序类型以及这些结构的使用情况。如果应用程序需要满足一些内存/性能标准,您肯定应该关心内存对齐和填充,但不仅如此 - 有一篇很好的文章 https://www.usenix.org/legacy/publications/library/proceedings/als00/2000papers/papers/full_papers/sears/sears_html/index.html 强调了最佳 CPU 缓存使用的主题以及结构布局和性能之间的相关性。它突出了缓存行对齐、错误共享等。
还有一个不错的 golang 工具 https://github.com/1pkg/gopium 可以帮助自动化这些优化,看看吧!
【讨论】:
【参考方案3】:目前没有编译时优化;这些值在 x64 上填充为 8 个字节。
您可以手动排列结构以优化空间利用;通常是从较大的类型变为较小的类型;例如 8 个连续的字节字段,将只使用 8 个字节,但单个字节将被填充到 8 字节对齐,请考虑:https://play.golang.org/p/0qsgpuAHHp
package main
import (
"fmt"
"unsafe"
)
type Compact struct
a, b uint64
c, d, e, f, g, h, i, j byte
// Larger memory footprint than "Compact" - but less fields!
type Inefficient struct
a uint64
b byte
c uint64
d byte
func main()
newCompact := new(Compact)
fmt.Println(unsafe.Sizeof(*newCompact))
newInefficient := new(Inefficient)
fmt.Println(unsafe.Sizeof(*newInefficient))
如果您考虑到这一点;您可以优化结构的内存占用。
【讨论】:
我还想补充一点,您可以使用structlayout 和aligncheck 等工具来可视化您的结构,以帮助您优化结构布局。以上是关于在 golang 中优化数据结构/字对齐填充的主要内容,如果未能解决你的问题,请参考以下文章