2016-08-21 17 views
9

Tương tự như những gì tôi đã học trong C++, tôi tin rằng đó là phần đệm gây ra sự khác biệt về kích thước của các thể hiện của cả hai cấu trúc.Tối ưu hóa cơ sở hạ tầng/liên kết từ đệm trong golang

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)) 
} 

Output:

amd64 
16 
24 
  • Có một quy tắc của ngón tay cái để làm theo khi xác định các thành viên struct? (như thứ tự tăng dần/giảm dần về kích thước của các loại)
  • Có tối ưu hóa thời gian biên dịch nào mà chúng ta có thể vượt qua, có thể tự động xử lý điều này không?
  • Hoặc tôi không nên lo lắng về điều này?
+1

tôi đã thực hiện một ví dụ mà có thể cung cấp một số hiểu biết https://play.golang.org/p/dNWspo2Dxv – jpgerek

Trả lời

10

Hiện tại không có tối ưu hóa thời gian biên dịch; các giá trị được đệm thành 8 byte trên x64.

Bạn có thể sắp xếp theo cách thủ công các cấu trúc để sử dụng tối ưu không gian; thường bằng cách đi từ các loại lớn hơn đến nhỏ hơn; liên tiếp 8 lĩnh vực byte ví dụ, sẽ chỉ sử dụng 8 byte, nhưng một byte duy nhất sẽ được đệm một sự liên kết 8 byte, xem xét việc này: 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)) 
} 

Nếu bạn thực hiện việc này vào xem xét; bạn có thể tối ưu hóa bộ nhớ của các cấu trúc của bạn.

+1

Tôi cũng muốn nói thêm rằng bạn có thể hình dung cấu trúc của bạn bằng cách sử dụng các công cụ như [structlayout] (https : //github.com/dominikh/go-structlayout) và [aligncheck] (https://github.com/opennota/check) để giúp bạn tối ưu hóa bố cục của các cấu trúc. – Chewxy

8

Hoặc tôi không nên lo lắng về điều này?

Có, bạn nên làm như vậy.
Điều này cũng được gọi là mechanical sympathy (xem này Go Time podcast episode), do đó, nó cũng phụ thuộc vào kiến ​​trúc phần cứng bạn đang biên dịch.

Xem như minh họa:

Các giá trị trong Go Slice là thẳng hàng 16-byte. Chúng không được căn chỉnh 32 byte.
Con trỏ đi được căn chỉnh theo byte.