Golang 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
你有没有注意到 TestStruct 其实是 32 bytes 的,那 Alloc 应该以 32 为单位增加。但你这里是 16 bytes 。有一个东西恰好是 16 bytes: reflect.StringHeader
更多关于Golang Go语言中的内存使用疑问的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
- 栈上的变量编译后就是一个
sub rsp, N
,内存用量不会变的
2. fmt.Print 内部有一个内存池
3. 打印结构体指针需要先反射判断是指针,打印一个&
,再递归打印结构体
有优化的,实际上他就是 Java 的 string intern ,只不过他支持泛型而已。
https://github.com/golang/go/issues/62483
第一个在栈上的,第三个逃逸了
好吧确实 为每个值返回一个全局唯一标识,同时这个值会被保存在池中
在Golang(通常简称为Go)中,内存管理是一个核心且高效的机制,得益于其内置的垃圾回收(GC)系统。这大大简化了开发者对内存管理的负担,但仍有一些关键点需要注意,以解决你在Go语言中的内存使用疑问。
-
内存分配与释放:Go使用逃逸分析来决定变量是在栈上分配还是在堆上分配。局部变量通常分配在栈上,而需要在函数外访问的变量或较大的数据结构则分配在堆上。GC会自动回收不再使用的堆内存,减少了内存泄漏的风险。
-
垃圾回收(GC):Go的GC是并发的,意味着它可以在程序运行时进行内存回收,减少停顿时间。但频繁的GC或长时间的GC停顿可能会影响性能。你可以通过调整GC参数或使用Go的pprof工具来分析和优化内存使用情况。
-
内存泄漏:尽管有GC,但不当的引用(如全局变量持有对局部变量的引用)仍可能导致内存泄漏。确保及时解除不必要的引用,特别是在使用闭包和goroutine时。
-
内存使用监控:使用Go的runtime包中的函数(如MemStats)来监控内存使用情况,可以帮助你发现潜在的内存问题。
总之,Go的内存管理机制虽然强大,但作为开发者,理解其工作原理并合理使用内存仍然很重要。通过良好的编程习惯和性能分析工具,你可以有效地管理和优化Go程序的内存使用。