1字节
var b int16 // 2字节
var c int32 // 4字节
var d int64 // 8字节
var e int32 // 4字节
var f int64 // 8字节
var g int // 8字节
var h string // 16字节
var i float32 // 4字节
var j float64 // 8字节
var k interface{} // 16字节
var l time.Time // 24字节,结构体字节数不稳定
var m time.Timer // 80字节,结构体字节不稳定
var n time.Duration // 8字节
var o []byte // 24字节
**/
例如,下面 User
type User1 struct {
Age uint8 // 1字节
Hunger int64 // 8字节
Happy bool // 1字节
}
可以看到10个字节就能保存这些属性,但是我们可以看下实际占用了多少字节:
go run struct.go
Size of main.User1 struct: 24 bytes
我们可以修改下User的结构
type User1 struct {
Hunger int64 // 8字节
Age uint8 // 1字节
Happy bool // 1字节
}
看下结果,减少了8个字节的长度
go run struct.go
Size of main.User1 struct: 16 bytes
诀窍就是根据字段的大小降序排列这些字段,后面的Age和Happy因为没有超过一个机器字,非配了8个字节。所以总共分配了16字节。
完整的代码如下:
package main
import (
"fmt"
"unsafe"
)
/**
var a bool // 1字节
var b int16 // 2字节
var c int32 // 4字节
var d int64 // 8字节
var e int32 // 4字节
var f int64 // 8字节
var g int // 8字节
var h string // 16字节
var i float32 // 4字节
var j float64 // 8字节
var k interface{} // 16字节
var l time.Time // 24字节,结构体字节数不稳定
var m time.Timer // 80字节,结构体字节不稳定
var n time.Duration // 8字节
var o []byte // 24字节
var p uint8 // 1字节
**/
type User1 struct {
Age uint8 // 1字节
Hunger int64 // 8字节
Happy bool // 1字节
}
type User2 struct {
Hunger int64 // 8字节
Age uint8 // 1字节
Happy bool // 1字节
}
var user1 User1
var user2 User2
func main() {
fmt.Printf("Size of %T struct: %d bytes\n", user1, unsafe.Sizeof(user1))
fmt.Printf("Size of %T struct: %d bytes\n", user2, unsafe.Sizeof(user2))
}
减少长生命周期对象的数量
与其让对象存在于堆上,不如将它们创建为值而不是按需引用。例如,如果我们需要用户请求中每个项目的一些数据,而不是预先计算并将其存储在一个长期存在的映射中,我们可以基于每个请求计算它以减少堆上的对象数量。
删除指针内的指针
如果我们有一个对象的引用,并且对象本身包含更多的指针,那么这些都被认为是堆上的单个对象,即使它们可能是嵌套的。通过将这些嵌套值更改为非指针,我们可以减少要扫描的对象的数量。
避免不必要的字符串/字节数组分配
由于字符串/字节数组在底层被视为指针,因此每个数组都是堆上的一个对象。如果可能,尝试将它们表示为其他非指针值,例如整数/浮点数、时间。
原文:
https://medium.com/@ali.can/memory-optimization-in-go-23a56544ccc0