在 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 中优化数据结构/字对齐填充的主要内容,如果未能解决你的问题,请参考以下文章

Golang优化之内存对齐

Apache 箭头、对齐和填充

堆排序介绍

字节对齐

将 BMP 像素数据加载到数组 C 中

结构体变量字节填充