-
Notifications
You must be signed in to change notification settings - Fork 0
/
memory_offset.go
76 lines (63 loc) · 2 KB
/
memory_offset.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package main
import (
"fmt"
"runtime"
"strconv"
"unsafe"
)
// https://dlintw.github.io/gobyexample/public/memory-and-sizeof.html
// Unlike C, there is no _#pragma pack_ in Go, the real memory allocation
// depends on its implementation.
type T struct {
B uint8 // is a byte
I int // it is int32 on my x86 32 bit PC
P *int // it is int32 on my x86 32 bit PC
S string
SS []string
}
var p = fmt.Println
// In this case, the `t := T{}` can not measured by this method.
func memUsage(m1, m2 *runtime.MemStats) {
p("Alloc:", m2.Alloc-m1.Alloc,
"TotalAlloc:", m2.TotalAlloc-m1.TotalAlloc,
"HeapAlloc:", m2.HeapAlloc-m1.HeapAlloc)
}
func main() {
// Here is a tricky to get pointer size
const PtrSize = 32 << uintptr(^uintptr(0)>>63)
p("PtrSize=", PtrSize)
p("IntSize=", strconv.IntSize)
var m1, m2, m3, m4, m5, m6 runtime.MemStats
runtime.ReadMemStats(&m1)
t := T{}
runtime.ReadMemStats(&m2)
p("sizeof(uint8)", unsafe.Sizeof(t.B),
"offset=", unsafe.Offsetof(t.B))
p("sizeof(int)", unsafe.Sizeof(t.I),
"offset=", unsafe.Offsetof(t.I))
p("sizeof(*int)", unsafe.Sizeof(t.P),
"offset=", unsafe.Offsetof(t.P))
p("sizeof(string)", unsafe.Sizeof(t.S),
"offset=", unsafe.Offsetof(t.S))
// Slice is a structure of Pointer, Len and Cap.
// Detail [here](http://blog.golang.org/go-slices-usage-and-internals)
p("sizeof([]string)", unsafe.Sizeof(t.SS),
"offset=", unsafe.Offsetof(t.SS))
// We can see the this structure is 4 + 4 + 4 + 8 + 12 = 32 bytes
// There are 3 padding bytes of first t.B expanded to 4 bytes.
p("sizeof(T)", unsafe.Sizeof(t))
// We will see 0 bytes, because it is on stack, so sizeof is the
// proper method to tell how much memory allocated.
memUsage(&m1, &m2)
// Even string assignment is in stack.
runtime.ReadMemStats(&m3)
t2 := "abc"
runtime.ReadMemStats(&m4)
memUsage(&m3, &m4)
// map will alloc memory in heap
runtime.ReadMemStats(&m5)
t3 := map[int]string{1: "x"}
runtime.ReadMemStats(&m6)
memUsage(&m5, &m6)
fmt.Println(t2, t3) // prevent compiler error
}