为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕哥9229398 2022-03-02 13:26:17
与我在 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))}输出:amd641624定义结构成员时是否有经验法则可以遵循?(如类型大小的升序/降序)是否有我们可以通过的编译时优化,可以自动处理这个问题?或者我根本不应该担心这个?
查看完整描述

3 回答

?
幕布斯6054654

TA贡献1876条经验 获得超7个赞

目前没有编译时优化;这些值在 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))

}

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


查看完整回答
反对 回复 2022-03-02
?
慕尼黑的夜晚无繁华

TA贡献1864条经验 获得超6个赞

或者我根本不应该担心这个?

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

如图所示:

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


查看完整回答
反对 回复 2022-03-02
?
守着一只汪

TA贡献1872条经验 获得超3个赞

这取决于您正在开发的应用程序的类型以及这些结构的使用。如果应用程序需要满足一些内存/性能标准,您绝对应该关心内存对齐和填充,但不仅如此 - 有一篇很好的文章https://www.usenix.org/legacy/publications/library/proceedings/als00/2000papers/论文/full_papers/sears/sears_html/index.html突出了最佳 CPU 缓存使用的主题以及结构布局和性能之间的相关性。它突出了缓存行对齐、错误共享等。

还有一个不错的 golang 工具https://github.com/1pkg/gopium可以帮助自动化这些优化,看看吧!


查看完整回答
反对 回复 2022-03-02
  • 3 回答
  • 0 关注
  • 182 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信