go 的内存使用疑问

80 天前
 chesha1

下面这段代码:

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

2192 次点击
所在节点    Go 编程语言
6 条回复
matrix1010
80 天前
你有没有注意到 TestStruct 其实是 32 bytes 的,那 Alloc 应该以 32 为单位增加。但你这里是 16 bytes 。有一个东西恰好是 16 bytes: reflect.StringHeader
whoami9894
80 天前
1. 栈上的变量编译后就是一个 `sub rsp, N`,内存用量不会变的
2. fmt.Print 内部有一个内存池
3. 打印结构体指针需要先反射判断是指针,打印一个 `&`,再递归打印结构体
xiaozirun
80 天前
unique 包对内存使用有优化效果吗,官方文档似乎只说了,他是只是用实现快速比等。
文档: https://pkg.go.dev/unique
picone
80 天前
@xiaozirun 有优化的,实际上他就是 Java 的 string intern ,只不过他支持泛型而已。

https://github.com/golang/go/issues/62483
leonshaw
80 天前
第一个在栈上的,第三个逃逸了
xiaozirun
80 天前
@picone 好吧确实 为每个值返回一个全局唯一标识,同时这个值会被保存在池中

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1068358

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX