下面这段代码:
package main
import (
"fmt"
"runtime"
"unique"
)
func printMemUsage() {
var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Printf("Alloc = %v B", m.Alloc)
fmt.Printf("\tTotalAlloc = %v B", m.TotalAlloc)
fmt.Printf("\n")
}
type TestStruct struct {
A float64
B float64
C float64
D float64
}
func main() {
testobj1 := TestStruct{A: 1, B: 2, C: 3, D: 4}
printMemUsage()
testobj2 := TestStruct{A: 1, B: 2, C: 3, D: 4}
printMemUsage()
testobj3 := TestStruct{A: 1, B: 2, C: 3, D: 4}
printMemUsage()
testobj4 := TestStruct{A: 1, B: 2, C: 3, D: 4}
printMemUsage()
fmt.Println(testobj1, testobj2, testobj3, testobj4)
fmt.Println("---------")
uniqueobj1 := unique.Make(TestStruct{A: 1, B: 2, C: 3, D: 4})
printMemUsage()
uniqueobj2 := unique.Make(TestStruct{A: 1, B: 2, C: 3, D: 4})
printMemUsage()
uniqueobj3 := unique.Make(TestStruct{A: 1, B: 2, C: 3, D: 4})
printMemUsage()
uniqueobj4 := unique.Make(TestStruct{A: 1, B: 2, C: 3, D: 4})
printMemUsage()
fmt.Println(uniqueobj1, uniqueobj2, uniqueobj3, uniqueobj4)
fmt.Println("---------")
testobj5 := TestStruct{A: 1, B: 2, C: 3, D: 4}
printMemUsage()
testobj6 := TestStruct{A: 1, B: 2, C: 3, D: 4}
printMemUsage()
testobj7 := TestStruct{A: 1, B: 2, C: 3, D: 4}
printMemUsage()
testobj8 := TestStruct{A: 1, B: 2, C: 3, D: 4}
printMemUsage()
fmt.Println(&testobj5, &testobj6, &testobj7, &testobj8)
}
输出结果是:
Alloc = 118256 B TotalAlloc = 118256 B
Alloc = 119704 B TotalAlloc = 119704 B
Alloc = 119720 B TotalAlloc = 119720 B
Alloc = 119736 B TotalAlloc = 119736 B
{1 2 3 4} {1 2 3 4} {1 2 3 4} {1 2 3 4}
---------
Alloc = 121056 B TotalAlloc = 121056 B
Alloc = 121072 B TotalAlloc = 121072 B
Alloc = 121088 B TotalAlloc = 121088 B
Alloc = 121104 B TotalAlloc = 121104 B
{0x1400001e180} {0x1400001e180} {0x1400001e180} {0x1400001e180}
---------
Alloc = 121152 B TotalAlloc = 121152 B
Alloc = 121200 B TotalAlloc = 121200 B
Alloc = 121248 B TotalAlloc = 121248 B
Alloc = 121296 B TotalAlloc = 121296 B
&{1 2 3 4} &{1 2 3 4} &{1 2 3 4} &{1 2 3 4}
本来是想试一下 unique 包对于内存的节约效果的,但是没想到第一种写法,每次也只增加了 16B ,和用了 unique 效果一样
而第三种写法,和第一种相比,确实每次用的内存多了,但是为什么后面的 fmt.Println 的写法区别,能影响前面的内存使用量
版本:go 1.23.0
平台:arm macos
上面这段代码有点陷阱,我自己回去又捣鼓了一下
这实际上是两个问题的杂糅,一个是unique
包的使用,先不谈
第二个,下面是一个最小化的实例,除了第一次,后面每次fmt.Printf
都会增加16B的内存,请问是什么导致的:
package main
import (
"fmt"
"runtime"
)
func main() {
var m runtime.MemStats
for i := 0; i < 10; i++ {
runtime.ReadMemStats(&m)
fmt.Printf("Alloc = %v B\n", m.Alloc)
}
}
关于逃逸,用go build -gcflags="-m" main.go
看了一下,确实在print这一行
./main.go:82:13: inlining call to fmt.Printf
./main.go:82:13: ... argument does not escape
./main.go:82:33: m.Alloc escapes to heap
但是又查了一番,没有资料提到这个16B是什么内容
1
matrix1010 87 天前 1
你有没有注意到 TestStruct 其实是 32 bytes 的,那 Alloc 应该以 32 为单位增加。但你这里是 16 bytes 。有一个东西恰好是 16 bytes: reflect.StringHeader
|
2
whoami9894 87 天前 1
1. 栈上的变量编译后就是一个 `sub rsp, N`,内存用量不会变的
2. fmt.Print 内部有一个内存池 3. 打印结构体指针需要先反射判断是指针,打印一个 `&`,再递归打印结构体 |
3
xiaozirun 87 天前 1
unique 包对内存使用有优化效果吗,官方文档似乎只说了,他是只是用实现快速比等。
文档: https://pkg.go.dev/unique |
4
picone 87 天前 1
|
5
leonshaw 87 天前 1
第一个在栈上的,第三个逃逸了
|