You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang内存基准测试结果异常及内存吞吐量获取咨询

Go基准测试问题与解决方案

一、软硬件配置

goos: windows
goarch: amd64
cpu: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz
go version: go1.21.5
Available Memory: 64GB

二、执行的基准测试命令

go test -bench=MyCodeBench -benchtime=1x -timeout=120m -benchmem -run=^$

注:因代码执行耗时久,需设置120分钟超时,否则会触发Test killed with quit: ran too long错误。

三、基准测试结果

MyCodeBench    1    776903113600 ns/op      402860098688 B/op       90982299 allocs/op

转换后显示402GB/op,但实际运行时任务管理器仅显示23GB内存占用——这里的B/op是基准测试期间累计内存分配总量,并非程序运行时的实时内存占用。


问题1:如何获取正确的基准测试结果?

要获取程序运行时的峰值内存占用(即当前内存使用量),可通过以下方式:

  • 手动监控内存状态:在基准测试代码中使用runtime.ReadMemStats()读取内存统计信息,关键字段说明:
    • HeapAlloc:当前堆内存中已分配的对象大小(实时内存占用核心参考)
    • HeapSys:程序从操作系统获取的总内存量
    • HeapInuse:当前正在使用的堆内存页大小
      示例代码:
    import "runtime"
    
    func BenchmarkMyCodeBench(b *testing.B) {
        var memStats runtime.MemStats
        var peakAlloc uint64
    
        // 测试前获取初始状态
        runtime.ReadMemStats(&memStats)
        initialAlloc := memStats.HeapAlloc
    
        b.ResetTimer()
        for i := 0; i < b.N; i++ {
            MyCode()
            // 监控过程中的峰值内存
            runtime.ReadMemStats(&memStats)
            currentAlloc := memStats.HeapAlloc - initialAlloc
            if currentAlloc > peakAlloc {
                peakAlloc = currentAlloc
            }
        }
        b.StopTimer()
    
        // 自定义输出峰值内存
        b.ReportMetric(float64(peakAlloc)/1024/1024, "MB_peak")
    }
    
  • 使用pprof分析:添加内存 profiling 参数生成分析文件,再通过工具查看峰值:
    go test -bench=MyCodeBench -benchtime=1x -timeout=120m -benchmem -run=^$ -memprofile=mem.prof
    
    执行完成后,运行go tool pprof mem.prof,在交互模式中输入top或web即可查看内存占用细节。

问题2:如何获取内存吞吐量(MB/s)?

调用SetBytes()未生效的常见原因是调用位置错误或传入参数不符合要求,正确实现步骤如下:

  1. 确定单次操作处理的字节数:比如你的代码处理了一段数据,计算这段数据的总字节数。
  2. 正确调用SetBytes():需在基准测试函数的循环结束后调用,且确保在ResetTimer()之后执行测试逻辑,避免初始化时间干扰。
    示例代码:
func BenchmarkMyCodeBench(b *testing.B) {
    // 初始化待处理数据(仅执行一次)
    inputData := []byte("your large data here")
    processedBytes := int64(len(inputData)) // 单次操作处理的字节数

    b.ResetTimer() // 重置计时器,排除初始化耗时
    for i := 0; i < b.N; i++ {
        YourProcessingFunction(inputData) // 执行测试代码
    }
    b.SetBytes(processedBytes) // 设置单次操作的字节数,基准测试工具会自动计算MB/s
}
  1. 验证输出:重新运行基准测试命令,结果中会新增MB/s指标,计算公式为:(总处理字节数) / (总耗时秒数) / 1024 / 1024。若仍未显示,检查是否processedBytes为0,或b.N为0(但你设置了-benchtime=1x,b.N应为1)。

内容的提问来源于stack exchange,提问作者Okay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 08:03:16