如何从runtime.MemStats获取Golang的RSS(Resident Set Size)?

huangapple go评论90阅读模式
英文:

how to get golang rss from runtime.MemStats

问题

我从runtime.MemStats中读取了(go)mem信息,但找不到rss值。我使用m.HeapSys-m.HeapReleased来计算,但发现该值与rss非常不相似。我还使用其他工具(github.com/shirou/gopsutil/process)转储了Rss,我想知道如何通过memstats获取rss,以及为什么m.HeapSys-m.HeapReleased和m.Sys与rss不相等,值如此不同?

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"io/ioutil"
	"log"
	"os"

	"github.com/dustin/go-humanize"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/shirou/gopsutil/process"

	"runtime"
	"strconv"
	"strings"
	"syscall"
	"time"
)

var pageSize = syscall.Getpagesize()

// rss返回当前进程的常驻集大小,单位为MiB
func rss() int {
	data, err := ioutil.ReadFile("/proc/self/stat")
	if err != nil {
		log.Fatal(err)
	}
	fs := strings.Fields(string(data))
	rss, err := strconv.ParseInt(fs[23], 10, 64)
	if err != nil {
		log.Fatal(err)
	}
	return int(uintptr(rss) * uintptr(pageSize) / (1 << 20)) // MiB
}

func getPs(pid int) {
	ps, _ := process.Processes()
	for _, p := range ps {
		if p.Pid == int32(pid) {
			mem, _ := p.MemoryInfo()
			fmt.Printf("通过进程获取的rss:%s\n", humanize.Bytes(mem.RSS))
		}
	}
}
func main() {
	pid := os.Getpid()

	go func() {
		for {
			var m runtime.MemStats
			runtime.ReadMemStats(&m)
			fmt.Printf("rss:%s\n", humanize.Bytes(m.HeapSys-m.HeapReleased))
			getPs(pid)
			fmt.Println("通过文件获取的rss:MB", rss())
			fmt.Println()
			time.Sleep(10 * time.Second)
		}
	}()
	r := gin.Default()
	r.GET("/metrics", gin.WrapH(promhttp.Handler()))
	log.Fatal(r.Run())
}

输出如下:

rss:6.6 MB
通过进程获取的rss:18 MB
通过文件获取的rss:MB 17

英文:

i read the (go)mem info from runtime.MemStats, but cant found rss value, i use m.HeapSys-m.HeapReleased, but found the value is very not like rss ,also i dump the Rss by other tool(github.com/shirou/gopsutil/process), i want to know how to get the rss by memstats, and why m.HeapSys-m.HeapReleased, and m.Sys not equal the rss, so different the value ?

package main

import (
	&quot;fmt&quot;
	&quot;github.com/gin-gonic/gin&quot;
	&quot;io/ioutil&quot;
	&quot;log&quot;
	&quot;os&quot;

	&quot;github.com/dustin/go-humanize&quot;
	&quot;github.com/prometheus/client_golang/prometheus/promhttp&quot;
	&quot;github.com/shirou/gopsutil/process&quot;

	&quot;runtime&quot;
	&quot;strconv&quot;
	&quot;strings&quot;
	&quot;syscall&quot;
	&quot;time&quot;
)

var pageSize = syscall.Getpagesize()

// rss returns the resident set size of the current process, unit in MiB
func rss() int {
	data, err := ioutil.ReadFile(&quot;/proc/self/stat&quot;)
	if err != nil {
		log.Fatal(err)
	}
	fs := strings.Fields(string(data))
	rss, err := strconv.ParseInt(fs[23], 10, 64)
	if err != nil {
		log.Fatal(err)
	}
	return int(uintptr(rss) * uintptr(pageSize) / (1 &lt;&lt; 20)) // MiB
}

func getPs(pid int) {
	ps, _ := process.Processes()
	for _, p := range ps {
		if p.Pid == int32(pid) {
			mem, _ := p.MemoryInfo()
			fmt.Printf(&quot;get by process rss:%s\n&quot;, humanize.Bytes(mem.RSS))
		}
	}
}
func main() {
	pid := os.Getpid()

	go func() {
		for {
			var m runtime.MemStats
			runtime.ReadMemStats(&amp;m)
			fmt.Printf(&quot;rss:%s\n&quot;, humanize.Bytes(m.HeapSys-m.HeapReleased))
			getPs(pid)
			fmt.Println(&quot;rss by file:MB&quot;, rss())
			fmt.Println()
			time.Sleep(10 * time.Second)
		}
	}()
	r := gin.Default()
	r.GET(&quot;/metrics&quot;, gin.WrapH(promhttp.Handler()))
	log.Fatal(r.Run())
}

*/

output like this

rss:6.6 MB
get by process rss:18 MB
rss by file:MB 17

答案1

得分: 1

最接近的值是memstats.Sys ~= RSS,但它们并不完全相等,因为RSS包含了一些其他的内容,比如共享库等,并且Go内存也可以来自虚拟内存,而不是全部来自RSS。

RSS的解释

英文:

The closest value is memstats.Sys ~= RSS, but they are not absolute equal , beacuse the rss contain some other like share lib,equal , and the
go memory alose can be from virtual memory,not all from rss

the RSS explation

答案2

得分: 0

你不能从runtime.MemStats中获取golang的rss信息。

m.HeapSys-m.HeapReleased和m.Sys与rss不相等,因为rss是一个完全不同的度量指标。

英文:

> [H]ow to get golang rss from runtime.MemStats [?]

You cannot. runtime.Memstats doesn't provide that information.

> why m.HeapSys-m.HeapReleased, and m.Sys not equal the rss [?]

Because RSS is a completely different metric.

huangapple
  • 本文由 发表于 2022年2月23日 23:59:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/71240260.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定