Оптимизация структуры данных/выравнивания слов в golang

подобно тому, что я узнал на 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
  • есть правило следовать при определении членов структуры? (например, по возрастанию/убыванию размера типов)
  • есть ли оптимизация времени компиляции, которую мы можем передать, которая может автоматически позаботиться об этом?
  • или я не должен беспокоиться об этом на всех?

2 ответов


В настоящее время нет оптимизации времени компиляции; значения дополняются до 8 байтов на x64.

вы можете вручную упорядочить структуры, чтобы оптимально использовать пространство; как правило, переходя от больших типов к меньшим; 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))
}

Если вы примите это во внимание; вы можете оптимизировать след памяти ваших структур.


или я вообще не должен беспокоиться об этом?

Да, вы должны.
Это также называется механические сочувствие (см. эпизод подкаста Go Time), поэтому это также зависит от аппаратной архитектуры, для которой вы компилируете.

посмотреть в качестве примера:

значения в срезах Go выровнены по 16 байтам. Они не выровнены по 32 байтам.
Указатели Go выровнены по байтам.