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

Go语言使用size库计算内存时遭遇DATA RACE问题求助

Go size库计算map内存时的数据竞争问题

我在用Go的size库计算变量运行时内存消耗,核心调用逻辑是Of函数传入interface,内部调用sizeOf遍历字段计算大小:

func Of(v interface{}) int {
    // Cache with every visited pointer so we don't count two pointers
    // to the same memory twice.
    cache := make(map[uintptr]bool)
    return sizeOf(reflect.Indirect(reflect.ValueOf(v)), cache)
}

当sizeOf处理map类型时,触发了数据竞争警告,对应的处理代码片段如下:

case reflect.Map:
    // return 0 if this node has been visited already (infinite recursion)
    if cache[v.Pointer()] {
        return 0
    }
    cache[v.Pointer()] = true
    sum := 0
    keys := v.MapKeys()
    for i := range keys {
        val := v.MapIndex(keys[i])
        // calculate size of key and value separately
        sv := sizeOf(val, cache)
        if sv < 0 {
            return -1
        }
        sum += sv
        sk := sizeOf(keys[i], cache)
        if sk < 0 {
            return -1
        }
        sum += sk
    }
    // Include overhead due to unused map buckets.  10.79 comes
    // from https://golang.org/src/runtime/map.go.
    return sum + int(v.Type().Size()) + int(float64(len(keys))*10.79)

错误信息

读取操作:

WARNING: DATA RACE
00:03:27  Read at 0x00c000996330 by goroutine 98:
00:03:27    reflect.maplen()
00:03:27        /home/git/.gimme/versions/go1.21.1.linux.amd64/src/runtime/map.go:1411 +0x0
00:03:27    reflect.Value.MapKeys()
00:03:27        /home/git/.gimme/versions/go1.21.1.linux.amd64/src/reflect/value.go:1788 +0x1a4

写入操作:

Previous write at 0x00c000996330 by goroutine 99:
00:03:27    runtime.mapdelete_fast64()
00:03:27        /home/git/.gimme/versions/go1.21.1.linux.amd64/src/runtime/map_fast64.go:273 +0x0
00:03:27    net/http.(*Transport).setReqCanceler()
00:03:27        /home/git/.gimme/versions/go1.21.1.linux.amd64/src/net/http/transport.go:1156 +0x204
00:03:27    net/http.(*persistConn).roundTrip.func1()
00:03:27        /home/git/.gimme/versions/go1.21.1.linux.amd64/src/net/http/transport.go:2622 +0x9a
00:03:27    runtime.deferreturn()
00:03:27        /home/git/.gimme/versions/go1.21.1.linux.amd64/src/runtime/panic.go:477 +0x30
00:03:27    net/http.(*Transport).roundTrip()

我试过在keys := v.MapKeys()代码周围加互斥锁,但没效果。想知道问题根源和可行的解决方案。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 19:13:15