如何将内存返回到操作系统



我的程序从操作系统获取内存,但不返回内存。它读取内存中的文件,处理它们,然后等待下一个文件。通常,我有小文件,但有时我有大文件。当我的程序处理大文件时,它从操作系统请求大量内存,但不返回。

我找到了与使用debug.FreeOSMemory()相关的问题/答案,但它不适用于我的代码示例。

我在实际系统中遇到了问题,但我可以用一个小例子重现它:

package main
import (
"fmt"
"math/rand"
"runtime"
"runtime/debug"
)
type Data struct {
a int
b int
c string
}
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
func randSeq(n int) string {
b := make([]rune, n)
for i := range b {
b[i] = letters[rand.Intn(len(letters))]
}
return string(b)
}
func stat(description string) {
var rtm runtime.MemStats
runtime.ReadMemStats(&rtm)
fmt.Printf("%s -> Alloc: %d; Sys: %dn", description, rtm.Alloc, rtm.Sys)
}
func mapAllocate() map[string]Data {
var data = make(map[string]Data)
for i := 0; i < 10000; i++ {
key := randSeq(100)
el := Data{
a: rand.Int(),
b: rand.Int(),
c: randSeq(rand.Intn(10000)),
}
data[key] = el
}
return data
}
func main() {
stat("Start program")
var result map[string]Data
for i := 0; i < 10; i++ {
result = mapAllocate()
stat("Map allocate")
result = make(map[string]Data)
runtime.GC()
debug.FreeOSMemory()
stat("GC call     ")
}
fmt.Println(len(result))
runtime.GC()
debug.FreeOSMemory()
for true {
stat("Waiting     ")
time.Sleep(30 * time.Second)
}
}

这是输出:

Start program -> Alloc: 129688; Sys: 71387144
Map allocate -> Alloc: 67501528; Sys: 143804680
GC call      -> Alloc: 130264; Sys: 143804680
Map allocate -> Alloc: 67611608; Sys: 143804680
GC call      -> Alloc: 130272; Sys: 143804680
Map allocate -> Alloc: 74416536; Sys: 143804680
GC call      -> Alloc: 130368; Sys: 143804680
Map allocate -> Alloc: 73419616; Sys: 143804680
GC call      -> Alloc: 130568; Sys: 143804680
Map allocate -> Alloc: 74005552; Sys: 143804680
GC call      -> Alloc: 130664; Sys: 143804680
Map allocate -> Alloc: 73491408; Sys: 143804680
GC call      -> Alloc: 130856; Sys: 143804680
Map allocate -> Alloc: 70013488; Sys: 143804680
GC call      -> Alloc: 130856; Sys: 143804680
Map allocate -> Alloc: 73025056; Sys: 143804680
GC call      -> Alloc: 130952; Sys: 143804680
Map allocate -> Alloc: 66745168; Sys: 143804680
GC call      -> Alloc: 131048; Sys: 143804680
Map allocate -> Alloc: 75094304; Sys: 143804680
GC call      -> Alloc: 131336; Sys: 143804680

当然,我不会在我的实际应用程序中调用 GC。我在这里使用它来演示我的问题。

如果理解正确:

  • 程序从堆中分配内存。第一次 Go 运行时没有足够的内存并从操作系统请求它。
  • 我调用 GC,它从内存中释放对象。但是 Go 运行时不会将此内存返回给操作系统。

这对我来说是一个问题,因为程序会获取大文件,获得大量内存,并且永远不会(几天(将其返回到操作系统,直到 OOM 杀手杀死程序的一个实例。

为什么 Go 运行时没有将此内存返回到操作系统,我该如何修复它?

去游乐场

操作系统:Linux 和 Mac OS

Go 返回内存,但需要一段时间。未使用的内存几乎从来都不是问题。

为什么 Go 运行时不会将此内存返回到操作系统

它返回此内存,但不会立即返回,因为分配/返回内存是一项成本高昂的操作。如果你等不及了...

我该如何解决它?

您可以尝试runtime/debug.FreeOSMemory是否真的是问题所在。

最新更新