如何从 runtime.MemStats 获取 golang rss

how to get golang rss from runtime.MemStats

我从 runtime.MemStats 读取了 (go)mem 信息,但找不到 rss 值,我使用 m.HeapSys-m.HeapReleased,但发现该值与 rss 非常不一样,我还通过其他工具转储 Rss(github.com/shirou/gopsutil/process),我想知道如何通过 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 returns the resident set size of the current process, unit in 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("get by process 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 by file: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
get by process rss:18 MB
rss by file:MB 17

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

你不能。 runtime.Memstats 没有提供该信息。

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

因为 RSS 是一个完全不同的指标。

最接近的值是 memstats.Sys ~= RSS,但它们不是绝对相等的,因为 rss 包含一些其他的东西,比如 share lib,equal 和 go memory alose 可以来自虚拟内存,而不是全部来自 rss

the RSS explation