Hiện tại hầu hết lập trình viên golang thường sẽ ít quan tâm đến việc sử dụng memory của nó, ai cũng cho rằng golang rất tốt cho việc tối ưu tài nguyên, nhưng khi bạn thực sự quan tâm thì đó là một sự lãng phí.
- Khi ứng dụng được chạy thì tất cả các biến, method điều được tạo ra và được allocate trên memory, khi memory bị cạn kiệt đồng nghĩa ứng dụng chết, do đó memory là vô cùng quan trọng nhé.
- Trong bài viết này tìm hiểu một số loại type cũng như byte của nó trên memory của golang, sau khi biết số byte thì việc tối ưu momery là cần thiết thế nào, ta sẽ dùng SizeOf
Vidụ:
Các type và byte của nó trong golang:
package main
import ( "fmt" "unsafe"
)
type Infomation struct { ValueString string ValueBool bool ValueUint8 uint8 ValueUint16 uint16 ValueUint32 uint32 ValueUint64 uint64 ValueUint uint Valueint8 int8 Valueint16 int16 Valueint32 int32 Valueint64 int64 Valueint int
}
func main() { item := Infomation{} fmt.Printf("string: %+v byte \n", unsafe.Sizeof(item.ValueString)) fmt.Printf("bool: %+v byte \n", unsafe.Sizeof(item.ValueBool)) fmt.Println() fmt.Printf("uint8: %+v byte \n", unsafe.Sizeof(item.ValueUint8)) fmt.Printf("uint16: %+v byte \n", unsafe.Sizeof(item.ValueUint16)) fmt.Printf("uint32: %+v byte \n", unsafe.Sizeof(item.ValueUint32)) fmt.Printf("uint64: %+v byte \n", unsafe.Sizeof(item.ValueUint64)) fmt.Printf("uint: %+v byte \n", unsafe.Sizeof(item.ValueUint)) fmt.Println() fmt.Printf("int8: %+v byte \n", unsafe.Sizeof(item.Valueint8)) fmt.Printf("int16: %+v byte \n", unsafe.Sizeof(item.Valueint16)) fmt.Printf("int32: %+v byte \n", unsafe.Sizeof(item.Valueint32)) fmt.Printf("int64: %+v byte \n", unsafe.Sizeof(item.Valueint64)) fmt.Printf("int: %+v byte \n", unsafe.Sizeof(item.Valueint))
}
=> Kết quả:
string: 16 byte
bool: 1 byte
uint8: 1 byte
uint16: 2 byte
uint32: 4 byte
uint64: 8 byte
uint: 8 byte
int8: 1 byte
int16: 2 byte
int32: 4 byte
int64: 8 byte
int: 8 byte
Với kết quả trên thì khi define các field trong golang cần quan tâm để giá trị của nó, tránh lãng phí tài nguyên.
Tối ưu khi define struct: sẽ có 2 struct và đặt vị trí field khác nhau thì sẽ có tổng số byte khác nhau:
package main import ( "fmt" "unsafe"
) type Infomation struct { ValueUint32 uint32 // 4 byte ValueBool bool // 1 byte ValueUint64 uint64 // 8 byte ValueBool2 bool // 1 byte
} type Infomation2 struct { ValueUint64 uint64 // 8 byte ValueUint32 uint32 // 4 byte ValueBool bool // 1 byte ValueBool2 bool // 1 byte
} func main() { item := Infomation{} item2 := Infomation2{} fmt.Println("tong 1: ", unsafe.Sizeof(item)) fmt.Println("tong 2: ", unsafe.Sizeof(item2))
}
tong 1: 24 tong 2: 16 => tại sao khi field là như nhau nhưng số byte lại khác nhau.
Giải Thích
- Mặc định đối với 1 type thì cần 4byte nếu type tiếp theo cộng lại hơn 4byte.
- Đối với struct Infomation; khi uint32 đứng đầu thì cần 4byte, tiếp đến là bool thì cần 1 byte nhưng cũng cần 4byte(bao gồm xử lý), uint64 thì cần 8byte, và cuối là bool thì cũng 4byte => tổng cộng là 24byte
- Đối với struct Infomation2; khi uint64 đứng đầu sẽ cần 8byte, tiếp là uint32 thì cần 4byte, sau đó là 2 biến bool mỗi biến là 1 byte tổng cũng là 4byte => tổng là 16byte
Tóm Lại:
Kinh nghiệm rút ra là khi khai báo 1 struct, thì ta nên để giá trị field có byte lớn lên phía trên, còn filed byte nhỏ xuống dưới.