2016-08-21 18 views
9

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 
  • 構造体のメンバを定義する際に従うべき経験則がありますか? (型のサイズの昇順/降順のように)
  • 自動的にこれを処理できるコンパイル時間の最適化はありますか?
  • 私はこれについて全く心配してはいけませんか?
+1

は、私はまた、あなたが[structlayout](HTTPSのようなツールを使用して、構造体を視覚化できることを追加したいいくつかの洞察を提供することができる例https://play.golang.org/p/dNWspo2Dxv – jpgerek

答えて

10

現在、コンパイル時の最適化はありません。値は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)) 
} 

あなたはこれを考慮する場合、あなたの構造体のメモリフットプリントを最適化することができます。

+1

を作りました://github.com/dominikh/go-structlayout)と[aligncheck](https://github.com/opennota/check)を参照して、構造体のレイアウトを最適化してください。 – Chewxy

8

これはまったく心配しないでください。

はい。
mechanical sympathy(これはGo Time podcast episode参照)とも呼ばれます。したがって、コンパイルするハードウェアアーキテクチャによっても異なります。

イラストなどを参照してください:

囲碁スライスの値は16バイト整列されています。 32バイト境界ではありません。
Goポインタはバイト境界整列されています。

関連する問題