Reputation: 16002
type T struct {
B uint8
S string
I int
}
func memUsage(mOld, mNew *runtime.MemStats) {
fmt.Println("Alloc:", mNew.Alloc-mOld.Alloc,
"HeapAlloc:", mNew.HeapAlloc-mOld.HeapAlloc,
"TotalAlloc:", mNew.TotalAlloc-mOld.TotalAlloc)
}
func main() {
var m1, m2, m3, m4, m5, m6 runtime.MemStats
runtime.ReadMemStats(&m1)
t := T{}
runtime.ReadMemStats(&m2)
fmt.Println(t)
memUsage(&m1, &m2)
runtime.ReadMemStats(&m3)
t2 := "abc"
runtime.ReadMemStats(&m4)
fmt.Println(t2)
memUsage(&m3, &m4)
runtime.ReadMemStats(&m5)
t3 := map[int]string{1: "x"}
runtime.ReadMemStats(&m6)
fmt.Println(t3)
memUsage(&m5, &m6)
memUsage(&m2, &m3)
memUsage(&m4, &m5)
}
Output
{0 0}
Alloc: 0 HeapAlloc: 0 TotalAlloc: 0
abc
Alloc: 0 HeapAlloc: 0 TotalAlloc: 0
map[1:x]
Alloc: 256 HeapAlloc: 256 TotalAlloc: 256
Alloc: 432 HeapAlloc: 432 TotalAlloc: 432
Alloc: 64 HeapAlloc: 64 TotalAlloc: 64
Upvotes: 1
Views: 190
Reputation: 166569
Variable t
is allocated on the stack.
package main
import (
"fmt"
)
type T struct {
B uint8
S string
I int
}
func main() {
t := T{}
fmt.Println(t)
}
Pseudo-assembler:
0x0021 00033 (t.go:14) LEAQ "".statictmp_0002+0(SB),BX
0x0028 00040 (t.go:14) LEAQ "".t+88(SP),BP
0x002d 00045 (t.go:14) MOVQ BP,DI
0x0030 00048 (t.go:14) MOVQ BX,SI
0x0033 00051 (t.go:14) DUFFCOPY ,$
References:
A Manual for the Plan 9 assembler
You have revised your question substantially. Next time, ask a new question.
You muddy the waters by your calls to the fmt
package. All we can see is that the fmt
package does some heap allocations. We would have to trace through hundreds of lines of code in the fmt
package to see what is happening. Also, the results are not reproducible.
I removed all the clutter:
package main
import (
"fmt"
"runtime"
)
type T struct {
B uint8
S string
I int
}
func memUsage(mOld, mNew *runtime.MemStats) {
fmt.Println("Alloc:", mNew.Alloc-mOld.Alloc,
"HeapAlloc:", mNew.HeapAlloc-mOld.HeapAlloc,
"TotalAlloc:", mNew.TotalAlloc-mOld.TotalAlloc)
}
func main() {
var m1, m2, m3, m4, m5, m6, m7 runtime.MemStats
runtime.ReadMemStats(&m1)
t := T{}
runtime.ReadMemStats(&m2)
_ = t
runtime.ReadMemStats(&m3)
t2 := "abc"
runtime.ReadMemStats(&m4)
_ = t2
runtime.ReadMemStats(&m5)
t3 := map[int]string{1: "x"}
runtime.ReadMemStats(&m6)
_ = t3
runtime.ReadMemStats(&m7)
memUsage(&m1, &m2)
memUsage(&m2, &m3)
memUsage(&m3, &m4)
memUsage(&m4, &m5)
memUsage(&m5, &m6)
memUsage(&m6, &m7)
}
Output:
Alloc: 0 HeapAlloc: 0 TotalAlloc: 0
Alloc: 0 HeapAlloc: 0 TotalAlloc: 0
Alloc: 0 HeapAlloc: 0 TotalAlloc: 0
Alloc: 0 HeapAlloc: 0 TotalAlloc: 0
Alloc: 256 HeapAlloc: 256 TotalAlloc: 256
Alloc: 0 HeapAlloc: 0 TotalAlloc: 0
It's easy to see that the stack is used except for creating the map which uses the stack and the heap.
Note: Go memory management is implementation dependent. It's frequently improved and it's about to be completely rewritten.
Upvotes: 3