在Go中分析内存时看似不一致的结果

 朗月清风的海角 发布于 2022-12-12 16:13

我最近在大型数据集上运行了一些用Go编写的数字代码,并且遇到了内存管理问题.在尝试分析问题时,我用三种不同的方式测量了程序的内存使用情况:使用Go的runtime/pprof包,使用unix time实用程序,以及手动累加我分配的数据大小.这三种方法并没有给我一致的结果.

下面是我正在分析的代码的简化版本.它分配了几个切片,将值放在每个索引处,并将每个切片放在父切片中:

package main

import (
    "fmt"
    "os"

    "runtime/pprof"
    "unsafe"
    "flag"
)

var mprof = flag.String("mprof", "", "write memory profile to this file")

func main() {
    flag.Parse()

    N := 1<<15
    psSlice := make([][]int64, N)
    _ = psSlice
    size := 0

    for i := 0; i < N; i++ {
        ps := make([]int64, 1<<10)
        for i := range ps { ps[i] = int64(i) }
        psSlice[i] = ps
        size += int(unsafe.Sizeof(ps[0])) * len(ps)
    }

    if *mprof != "" {
        f, err := os.Create(*mprof)
        if err != nil { panic(err) }
        pprof.WriteHeapProfile(f)
        f.Close()
    }

    fmt.Printf("total allocated: %d MB\n", size >> 20)
}

使用该命令运行此$ time time -f "%M kB" ./mem_test -mprof=out.mprof结果将导致输出:

total allocated: 256 MB
1141216 kB

real    0m0.150s
user    0m0.031s
sys 0m0.113s

这里第一个数字,256 MB,只是从中计算的数组的大小,unsafe.Sizeof第二个数字,1055 MB,是time报告的数字.运行pprof工具会导致

(pprof) top1
Total: 108.2 MB
   107.8  99.5%  99.5%    107.8  99.5% main.main

对于较小或较大长度的切片,这些结果可以按照您期望的方式平滑地缩放.

为什么这三个数字不紧密排列?

1 个回答
  • 首先,您需要提供一个无错误的示例.让我们从基本数字开始.例如,

    package main
    
    import (
        "fmt"
        "runtime"
        "unsafe"
    )
    
    func WriteMatrix(nm [][]int64) {
        for n := range nm {
            for m := range nm[n] {
                nm[n][m]++
            }
        }
    }
    
    func NewMatrix(n, m int) [][]int64 {
        a := make([]int64, n*m)
        nm := make([][]int64, n)
        lo, hi := 0, m
        for i := range nm {
            nm[i] = a[lo:hi:hi]
            lo, hi = hi, hi+m
        }
        return nm
    }
    
    func MatrixSize(nm [][]int64) int64 {
        size := int64(0)
        for i := range nm {
            size += int64(unsafe.Sizeof(nm[i]))
            for j := range nm[i] {
                size += int64(unsafe.Sizeof(nm[i][j]))
            }
        }
        return size
    }
    
    var nm [][]int64
    
    func main() {
        n, m := 1<<15, 1<<10
        var ms1, ms2 runtime.MemStats
        runtime.ReadMemStats(&ms1)
        nm = NewMatrix(n, m)
        WriteMatrix(nm)
        runtime.ReadMemStats(&ms2)
        fmt.Println(runtime.GOARCH, runtime.GOOS)
        fmt.Println("Actual:  ", ms2.TotalAlloc-ms1.TotalAlloc)
        fmt.Println("Estimate:", n*3*8+n*m*8)
        fmt.Println("Total:   ", ms2.TotalAlloc)
        fmt.Println("Size:    ", MatrixSize(nm))
    
        // check top VIRT and RES for COMMAND peter
        for {
            WriteMatrix(nm)
        }
    }
    

    输出:

    $ go build peter.go && /usr/bin/time -f "%M KiB" ./peter
    amd64 linux
    Actual:   269221888
    Estimate: 269221888
    Total:    269240592
    Size:     269221888
    ^C
    Command exited with non-zero status 2
    265220 KiB
    $
    
    $ top
    VIRT 284268 RES 265136 COMMAND peter
    

    这是你所期望的吗?

    请参阅MatrixSize计算内存大小的正确方法.

    在允许我们使用top命令的无限循环中,通过更新矩阵将矩阵固定为常驻.

    运行此程序时会得到什么结果?


    BUG:

    你的结果/usr/bin/time1056992 KiB太大了四倍.这是在你的版本中的错误/usr/bin/time,ru_maxrss在千字节的页面没有报道.我的Ubuntu版本已修补.

    参考文献:

    Re:GNU时间:结果不正确

    时间1.7计算Linux上的rusage错误

    GNU项目档案:时间

    Ubuntu中的"时间"1.7-24源代码包.ru_maxrss报告以KB为单位而不是页面.(关闭:#649402)

    #PATY]时间过高估计最多RSS 4倍 - Debian Bug报告日志

    主题:修复ru_maxrss报告作者:Richard Kettlewell Bug-Debian:http://bugs.debian.org/cgi-bin/bugreport.cgi?video = 649402

    --- time-1.7.orig/time.c
    +++ time-1.7/time.c
    @@ -392,7 +398,7 @@
                 ptok ((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS (v));
            break;
          case 'M':       /* Maximum resident set size.  */
    -       fprintf (fp, "%lu", ptok ((UL) resp->ru.ru_maxrss));
    +       fprintf (fp, "%lu", (UL) resp->ru.ru_maxrss);
            break;
          case 'O':       /* Outputs.  */
            fprintf (fp, "%ld", resp->ru.ru_oublock);
    

    2022-12-12 16:16 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有