我的程序从操作系统获取内存,但不返回内存。它读取内存中的文件,处理它们,然后等待下一个文件。通常,我有小文件,但有时我有大文件。当我的程序处理大文件时,它从操作系统请求大量内存,但不返回。
我找到了与使用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
这是否真的是问题所在。