优化golang中的数据结构/字对齐填充

noh*_*hup 11 struct padding go memory-alignment

与我在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))
}
Run Code Online (Sandbox Code Playgroud)

输出:

amd64
16
24
Run Code Online (Sandbox Code Playgroud)
  • 在定义struct成员时是否遵循经验法则?(如类型大小的升序/降序)
  • 是否有我们可以通过的编译时优化,可以自动处理这个?
  • 或者我不应该担心这一点?

Mar*_*her 12

目前还没有编译时优化; 在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))
}
Run Code Online (Sandbox Code Playgroud)

如果你考虑到这一点; 您可以优化结构的内存占用.

  • 我还想补充一点,您可以使用[structlayout](https://github.com/dominikh/go-structlayout)和[aligncheck](https://github.com/opennota/)等工具来可视化您的结构.检查)以帮助您优化结构的布局. (2认同)

Von*_*onC 10

或者我不应该担心这一点?

是的你应该.
这也称为机械同情(参见此Go Time播客剧集),因此它还取决于您正在编译的硬件架构.

如图所示:

Go切片中的值是16字节对齐的.它们不是32字节对齐的.
Go指针是字节对齐的.