内存使用[] [] string vs struct包含[]字符串

pti*_*son 7 memory struct memory-leaks go slice

附加到[][]string分析后显示应用程序使用大约145MiB的内存.

defer profile.Start(profile.MemProfile).Stop()

f, _ := os.Open("test.csv") // 100 MiB File
r := csv.NewReader(f)

var records [][]string
for {
    values, err := r.Read()
    if err == io.EOF {
        break
    }
    records = append(records, values)
}
Run Code Online (Sandbox Code Playgroud)

将切片存储在结构中并附加应用程序使用大约260MiB的内存时.

defer profile.Start(profile.MemProfile).Stop()

type record struct {
    values []string
}

f, _ := os.Open("test.csv") // 100 MiB File
r := csv.NewReader(f)

var records []record
for {
    values, err := r.Read()
    if err == io.EOF {
        break
    }
    r := record{values: values}
    records = append(records, r)
}
Run Code Online (Sandbox Code Playgroud)

感觉它在第二个例子中使用了两倍的内存.有人可以解释为什么第二个例子使用更多内存?

小智 1

对于那些在 go 1.12 和 go 1.15 之间使用的人来说,debug.FreeOSMemory()不会将可用内存返回给操作系统,因此 htop/top 将显示错误的数字,或者如果您依靠 RSS 来监控您的应用程序,那将是错误的。

这是因为 Golang (1.12 - 1.15) 中的运行时使用MADV_FREE. MADV_DONTNEED<= Go (1.11) 和 Go (1.16 - 几天前发布) 使用 .<= Go (1.11) 和 Go (1.16 - 几天前发布) MADV_DONTNEED

Go 1.16 恢复到MADV_DONTNEED.

请在此处找到变更日志图像和变更日志 URL 。

请升级以获得有关内存使用情况的可预测分析。如果您想使用 GoLang(1.12-1.15) 并且仍然想使用MADV_DONTNEED,请使用GODEBUG=madvdontneed=1./main 运行您的二进制文件。 在此输入图像描述