Go's Garbage collector isn't releasing mem

2020-08-05 11:30发布

问题:

This question already has an answer here:
Closed 2 years ago.

I wrote a simple http golang webserver to test the Go garbage collection (releasing memory of inaccessible pointers), But in strees testing ,I understand it consumes excessive ram.

According to some question/answers, I found out Golang does garbage collection automatically, manage the extra memory itself and doesn't get back memory to OS at once. Some results:

  • The webserver release ram after about 5mins.

  • The webserver consumes ram until it gets up to specific level and requesting more connections not gets more memory(about 4GB in my case)

Consuming 4GB of ram isn't cool! So i added a Goroutine to my code that gets the extra memory back to OS.

The code:

type t struct{
    a       []string
    b       map[string]string
}
var x t = t{
    a:  []string{"1","2"},
    b:  make(map[string]string),
}

func handler(w http.ResponseWriter, r *http.Request) {
    x := &t{}
    fmt.Fprintf(w, "pong", r.URL.Path[1:])
}

func main() {
    http.HandleFunc("/ping", handler)
    go func(){
        for {
            time.Sleep(10 * time.Second)
            fmt.Println("Free up memory...")
            debug.FreeOSMemory() 
        }

    }()
    log.Fatal(http.ListenAndServe(":8080", nil))
}

For stress testing i use Apache Bench:

ab -c 100 -n 400000 http://127.0.0.1:8080/ping

I ran above command about 10 times continuously to check the ram usage. It works very well, But the problem is, Is there any standard way that Go releases the memory better!?

I know in some cases, it's good that Go manages the memory itself instead of repetitive releasing and getting back memory from OS, But in my case, 5 minutes delay is very much to releasing memory.

回答1:

You might want to call FreeOSMemory from runtime/debug

But you probably should not. Try instead to tune the GC for your particular application and usage (perhaps using SetGCPercent). It is likely that using FreeOSMemory too often would decrease performance, so be sure to benchmark.

Notice that the garbage collection implementation has improved in recent versions of Go, and is different in various Go implementations (e.g. in GCC Go).

Don't confuse RAM usage (the RAM is managed by your OS kernel, not by your Go process), virtual memory, virtual address space. Read about RSS, demand paging, thrashing.

For an overview of garbage collection techniques, read The GC Handbook.

For a better understanding of OSes, read Operating Systems: Three Easy Pieces

See also Linux ate my RAM.