首页 > 系统相关 >Golang初学:获取程序内存使用情况,std runtime

Golang初学:获取程序内存使用情况,std runtime

时间:2024-05-17 21:32:47浏览次数:35  
标签:std Alloc fmt Golang 内存 MiBHeapAlloc runtime MiBTotalAlloc MiBSys

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 相关代码

前】、中】 相同,后】 的内存使用 会多一点。

前】
Alloc = 0 MiB
TotalAlloc = 0 MiB
Sys = 6 MiB
HeapAlloc = 0 MiB
HeapSys = 3 MiB
NumGC = 0
s1: len=1000000 cap=1000000

中】
Alloc = 0 MiB
TotalAlloc = 7 MiB
Sys = 14 MiB
HeapAlloc = 0 MiB
HeapSys = 11 MiB
NumGC = 1

后】
Alloc = 0 MiB
TotalAlloc = 7 MiB
Sys = 14 MiB
HeapAlloc = 0 MiB
HeapSys = 11 MiB
NumGC = 1

 

2、 增加 填充数据部分

前】、中】 和 之前相同,后】  增加了很多,这里 1百万 的数据,后】 的 Sys 达到了 54MB。

前】
Alloc = 0 MiB
TotalAlloc = 0 MiB
Sys = 6 MiB
HeapAlloc = 0 MiB
HeapSys = 3 MiB
NumGC = 0
s1: len=1000000 cap=1000000

中】
Alloc = 7 MiB
TotalAlloc = 7 MiB
Sys = 14 MiB
HeapAlloc = 7 MiB
HeapSys = 11 MiB
NumGC = 1

后】
Alloc = 0 MiB
TotalAlloc = 62 MiB
Sys = 54 MiB
HeapAlloc = 0 MiB
HeapSys = 51 MiB
NumGC = 5

ben发布于博客园

3、再增加 time.Sleep 部分

1、3 秒都行。

前】
Alloc = 0 MiB
TotalAlloc = 0 MiB
Sys = 6 MiB
HeapAlloc = 0 MiB
HeapSys = 3 MiB
NumGC = 0
s1: len=1000000 cap=1000000

中】
Alloc = 7 MiB
TotalAlloc = 7 MiB
Sys = 14 MiB
HeapAlloc = 7 MiB
HeapSys = 11 MiB
NumGC = 1

后】
Alloc = 0 MiB
TotalAlloc = 62 MiB
Sys = 55 MiB
HeapAlloc = 0 MiB
HeapSys = 51 MiB
NumGC = 5

 

测试小结

ReadMemStats 函数 获取的内存信息,存在一些延迟——毫秒级,使用时需要注意。

 

控制 golang 程序内存使用的方式

两千万数据量的测试结果

在上面的程序中, 数据量是 一百万,将其增加到 二千万 进行测试,其内存分配肯定会增加很多。

结果如下:其最终 Sys 达到了 895MB!ben发布于博客园

要是数据量再增大若干倍,只怕我的测试电脑要崩溃了,或者,程序先崩溃。

前】
Alloc = 0 MiB
TotalAlloc = 0 MiB
Sys = 5 MiB
HeapAlloc = 0 MiB
HeapSys = 3 MiB
NumGC = 0
s1: len=20000000 cap=20000000

中】
Alloc = 152 MiB
TotalAlloc = 152 MiB
Sys = 162 MiB
HeapAlloc = 152 MiB
HeapSys = 159 MiB
NumGC = 1

后】
Alloc = 0 MiB
TotalAlloc = 1252 MiB
Sys = 895 MiB
HeapAlloc = 0 MiB
HeapSys = 891 MiB
NumGC = 4

 

初步探索

咨询了 #通义千问 ,其介绍了两种方式:

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发布于博客园

 

标签:std,Alloc,fmt,Golang,内存,MiBHeapAlloc,runtime,MiBTotalAlloc,MiBSys
From: https://www.cnblogs.com/luo630/p/18198598

相关文章

  • golang开发
    项目目录结构democonfigconfig.goconfconfig.yamllogmain.go代码config.gopackageconfigimport("fmt""github.com/toolkits/pkg/file""github.com/toolkits/pkg/logger""os")typeCon......
  • golang context 特点,和自己定义分类有什么区分
     context包的特点包括:1信号传递:取消信号:context提供了一个取消机制,允许一个父级goroutine在必要的时候通知其子级goroutines任务应该停止执行。 截止时间:可以设置一个截止时间,当超过这个时间时,上下文自动变为取消状态。 超时:类似截止时间,但通常基于从当前......
  • python代码上传文件到fastdfs
    Install直接pip安装,需要Python3.10+pipinstallfastdfs-clientInitialclient可以用其他教程的client.conf配置文件的方式,也可以直接传入ip列表进行初始化fromfastdfs_clientimportFastdfsClientclient=FastdfsClient(trackers=('ip1','ip2',...))Uploadbyfil......
  • Golang初学:文件操作,标准库
    goversiongo1.22.1windows/amd64Windows11+amd64x86_64x86_64GNU/Linux--- 序章读取文件内容,写入新文件(可能存在、也可能不存在)。 相关标准库iofsospathfilepath ShowCodefuncCopyFile(){ //测试文件拷贝 varfsrc,fdststring varstartt......
  • kotlin-stdlib-jdk8 的作用
    在kotlin1.8.0之前,kotlin的标准库kotlin-stdlib的jvmTarget是Java1.6,但是如果程序的jvmTarget是1.7或1.8,则可以手动添加kotlin-stdlib-jdk7或kotlin-stdlib-jdk8来使用kotin对相关Java版本提供的API(如:Java1.7中AutoCloseable相关的API和Java1.8......
  • C++封装dll(__cdecl和__stdcall)
    【1】使用__stdcall还需要添加def文件编译,使用工具DEPENDS.EXE打开dll文件成功。【2】使用__cdecl直接编译即可,不需要导入def文件......
  • FastDFS系统支持文件迁移吗?
    大家知道,FastDFS架构是下图这样子。  大家可否知道,将一个fdfs系统里存储的文件迁移到另一个fdfs系统里,这个文件在新的fdfs系统能通过client正常访问吗?先说答案:fastdfs系统支持文件迁移。亲测为证!这一个技术点很重要,对于我们即将要做的工作来说。就是说,将一个fdfs存储服务......
  • golang- 实现多环境配置
    需要安装插件gogetgopkg.in/yaml.v3配置yaml文件  然后配置数据块与yaml结构相同,用来接收数据,字段需要配置映射关系,如下完整的执行代码如下//初始化yaml文件funcdoYaml(){envName:=ParamsObj.EnvifStringUtil.IsEmpty(envName){envNa......
  • Golang初学:time包,Ticker,Timer
    goversiongo1.22.1windows/amd64Windows11+amd64x86_64x86_64GNU/Linux--- 序章packagetimehttps://pkg.go.dev/timePackagetimeprovidesfunctionalityformeasuringanddisplayingtime.测量、显示时间。 本文展示Ticker、Timer的基本使用。 ......
  • golang进程通过共享内存和C++进程进行通信
    目录serverclientserverC++可以使用POSIX共享内存API来创建和管理共享内存server.cpp#include<fcntl.h>#include<sys/mman.h>#include<sys/stat.h>#include<unistd.h>#include<cstring>#include<iostream>constchar*S......