Golang初学:获取程序内存使用情况,std runtime
go version go1.22.1 windows/amd64
Windows 11 + amd64
x86_64 x86_64 GNU/Linux
---
序章
本文介绍 golang 程序 占用内存的监控:
使用 std runtime 的 ReadMemStats 函数。
ReadMemStats 函数
https://pkg.go.dev/runtime@go1.22.3
// 函数
func ReadMemStats(m *MemStats)
// 结构体
type MemStats struct {
// 多个公开字段
}
ReadMemStats 介绍:
ReadMemStats populates m with memory allocator statistics. The returned memory allocator statistics are up to date as of the call to ReadMemStats. This is in contrast with a heap profile, which is a snapshot as of the most recently completed garbage collection cycle. |
翻译: 读取模块统计数据用内存分配器统计信息填充 m。 返回的内存分配器统计信息是在调用读取内存统计数据时的最新数据。 这与堆配置文件形成对比,它是最近完成的垃圾收集周期的快照。 ——金山词霸 |
测试代码
场景:制造一个长度为n的切片,再往其中填充数据,检查 前、中、后 三个内存使用情况。ben发布于博客园
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
fmt.Println("前】")
readMem()
const slen = 1_000_000
s1 := make([]int, slen)
fmt.Printf("s1: len=%d cap=%d\n", len(s1), cap(s1))
time.Sleep(3 * time.Second) // 必须,否则,下面这个 readMem() 的结果和上面的相同
fmt.Println("\n中】")
readMem()
// 填充数据
// 填充后,内存使用才有变化
for i := range [slen]struct{}{} {
s1 = append(s1, i)
}
time.Sleep(3 * time.Second) // 非必须
fmt.Println("\n后】")
readMem()
}
func readMem() {
var m runtime.MemStats
runtime.ReadMemStats(&m)
// fmt.Println(ms) // 太复杂了
// 内存 通义千问
// 打印一些关键的内存统计信息
fmt.Printf("Alloc = %v MiB\n", m.Alloc/1024/1024) // 分配但未释放的内存
fmt.Printf("TotalAlloc = %v MiB\n", m.TotalAlloc/1024/1024) // 程序启动以来分配的总内存
fmt.Printf("Sys = %v MiB\n", m.Sys/1024/1024) // 从操作系统分配的总内存
fmt.Printf("HeapAlloc = %v MiB\n", m.HeapAlloc/1024/1024) // 从堆上分配但未释放的内存
fmt.Printf("HeapSys = %v MiB\n", m.HeapSys/1024/1024) // 由Go分配的堆内存的系统内存大小
fmt.Printf("NumGC = %v\n", m.NumGC) // 进行的GC次数
}
注意其中的 1)time.Sleep,2)填充数据 两部分,下面测试期间 可能会注释掉。
测试结果
3种情况的测试结果。
1、没有 填充数据、time.Sleep 相关代码
前】、中】 相同,后】 的内存使用 会多一点。
前】 中】 后】 |
2、 增加 填充数据部分
前】、中】 和 之前相同,后】 增加了很多,这里 1百万 的数据,后】 的 Sys 达到了 54MB。
前】 中】 后】 |
ben发布于博客园
3、再增加 time.Sleep 部分
1、3 秒都行。
前】 中】 后】 |
测试小结
ReadMemStats 函数 获取的内存信息,存在一些延迟——毫秒级,使用时需要注意。
控制 golang 程序内存使用的方式
两千万数据量的测试结果
在上面的程序中, 数据量是 一百万,将其增加到 二千万 进行测试,其内存分配肯定会增加很多。
结果如下:其最终 Sys 达到了 895MB!ben发布于博客园
要是数据量再增大若干倍,只怕我的测试电脑要崩溃了,或者,程序先崩溃。
前】 中】 后】 |
初步探索
咨询了 #通义千问 ,其介绍了两种方式:
1、间接方式:Docker
示例,
docker run -it --memory="512m" --cpus="0.5" your-image-name
2、直接方式:Linux 下的 cgroups
2.1、在 golang 程序中使用 cgroups
若需直接在Go程序中操作cgroups,可以使用第三方库,
如`github.com/opencontainers/runc/libcontainer`或`github.com/containerd/cgroups`。
注,cgroups v1 和 v2 有些差别。
注,未亲测 TODO。
ben发布于博客园
间接方式 不用多说,现在都用上 Docker、Kubernetes 了,很简单。
直接方式:需要做更多探索。要知道,cgroups 也是 容器技术 的底层,了解并掌握是有很多好处的。
END.
ben发布于博客园
本文链接:
https://www.cnblogs.com/luo630/p/18198598
ben发布于博客园
参考资料
1、通义千问
https://tongyi.aliyun.com/qianwen/
2、
ben发布于博客园
ben发布于博客园