4
package main

import (
        "fmt"
        "net/http"
        "runtime"
)

func handler(w http.ResponseWriter, r *http.Request) {
       largeMemAlloc := make([]int, 100000000)
       largeMemAlloc[1] = 100//lol
       fmt.Fprintf(w, "hi from handler")
       runtime.GC()
}

func main() {
       http.HandleFunc("/", handler)
       http.ListenAndServe(":7777", nil)
}

Once I visit http://127.0.0.1:7777 4-5 times the memory used goes in to GBs.

Its been around 4-5 mins and the memory is still unclaimed by the OS. Why is this happening?

What am I doing wrong?

I am compiling this in go 1.5

Edit : After 10 mins, the memory usage has gone down to just 50mb. But I dont understand why it takes so long to reclaim this block of memory. I feel like I am doing something horribly wrong.

Gen Shani
  • 57
  • 3
  • 11
    Go does not immediately release memory back to the OS — because a program that uses large chunks of memory will typically use them again. Only after ~7 - 10 minutes will unused memory be released - see here http://stackoverflow.com/questions/24376817/go-1-3-garbage-collector-not-releasing-server-memory-back-to-system – elithrar Sep 26 '15 at 20:04
  • I see, thanks very much. – Gen Shani Sep 26 '15 at 20:14
  • @elithrar That is a good explanation! Mind providing an answer for Gen's question, too? – user918176 Nov 20 '15 at 21:14

1 Answers1

2

Go does not release memory back to the OS immediately, even if it is reclaimed via garbage collection (GC). This is a performance improvement as it may need the memory again. You are not doing anything wrong. Without limited knowledge of the future demand and considering the overhead of compacting, freeing and allocating memory from the OS, every GC needs to make this performance trade-off. There was research into making the API the OS provides for this more effective in the context of the JVM and Linux kernel. User space OOM handling is a more recent, less ambitious Linux kernel development that could be used by a GC to more early release memory when it is most needed.

As far as I know there is no official upper limit for how long Go keeps memory. However in Go 1.3 Garbage collector not releasing server memory back to system it was experimentally verified to be 9 minutes (a GC which occurs at least after 2 minutes + 7 minutes holding memory in reserve).

You can manually trigger this by calling runtime.debug.FreeOSMemory(), however this is usually not a good idea except for debugging purposes.

Jan Zerebecki
  • 825
  • 7
  • 18