Golang Go语言中的内存使用疑问

发布于 1周前 作者 nodeper 来自 Go语言

下面这段代码:

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


Golang Go语言中的内存使用疑问

更多关于Golang Go语言中的内存使用疑问的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

7 回复

你有没有注意到 TestStruct 其实是 32 bytes 的,那 Alloc 应该以 32 为单位增加。但你这里是 16 bytes 。有一个东西恰好是 16 bytes: reflect.StringHeader

更多关于Golang Go语言中的内存使用疑问的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


  1. 栈上的变量编译后就是一个 sub rsp, N,内存用量不会变的
    2. fmt.Print 内部有一个内存池
    3. 打印结构体指针需要先反射判断是指针,打印一个 &,再递归打印结构体

unique 包对内存使用有优化效果吗,官方文档似乎只说了,他是只是用实现快速比等。
文档: https://pkg.go.dev/unique

有优化的,实际上他就是 Java 的 string intern ,只不过他支持泛型而已。

https://github.com/golang/go/issues/62483

第一个在栈上的,第三个逃逸了

好吧确实 为每个值返回一个全局唯一标识,同时这个值会被保存在池中

在Golang(通常简称为Go)中,内存管理是一个核心且高效的机制,得益于其内置的垃圾回收(GC)系统。这大大简化了开发者对内存管理的负担,但仍有一些关键点需要注意,以解决你在Go语言中的内存使用疑问。

  1. 内存分配与释放:Go使用逃逸分析来决定变量是在栈上分配还是在堆上分配。局部变量通常分配在栈上,而需要在函数外访问的变量或较大的数据结构则分配在堆上。GC会自动回收不再使用的堆内存,减少了内存泄漏的风险。

  2. 垃圾回收(GC):Go的GC是并发的,意味着它可以在程序运行时进行内存回收,减少停顿时间。但频繁的GC或长时间的GC停顿可能会影响性能。你可以通过调整GC参数或使用Go的pprof工具来分析和优化内存使用情况。

  3. 内存泄漏:尽管有GC,但不当的引用(如全局变量持有对局部变量的引用)仍可能导致内存泄漏。确保及时解除不必要的引用,特别是在使用闭包和goroutine时。

  4. 内存使用监控:使用Go的runtime包中的函数(如MemStats)来监控内存使用情况,可以帮助你发现潜在的内存问题。

总之,Go的内存管理机制虽然强大,但作为开发者,理解其工作原理并合理使用内存仍然很重要。通过良好的编程习惯和性能分析工具,你可以有效地管理和优化Go程序的内存使用。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!