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

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


我找到了与 using 相关的问题/答案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: %d\n", 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)

    }

}


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


如果理解正确:


程序从堆中分配内存。Go 运行时第一次没有足够的内存并从操作系统请求它。

我调用 GC,它从内存中释放对象。但是 Go 运行时不会将此内存返回给操作系统。

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


为什么 Go 运行时不会将此内存返回给操作系统,我该如何解决?


慕工程0101907
浏览 197回答 2
2回答

慕容708150

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

呼如林

为什么 Go 运行时不会将此内存返回给操作系统它返回此内存,但不会立即返回,因为分配/返回内存是一项昂贵的操作。如果你等不及...我该如何解决?runtime/debug.FreeOSMemory如果这确实是问题,您可以尝试。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go