-1

I'm trying to release the slice completely, so the memory goes back to the OS; however, when I try to dereference it by doing slice = nil, nothing happens.

I have tried also using runtime.GC() and debug.FreeOSMemory(), but neither of those helped.

Here's the code I have:

package main

import (
    "fmt"
    "runtime"
    "runtime/debug"
)

func printMemStats(stage string) {
    var m runtime.MemStats
    runtime.ReadMemStats(&m)
    fmt.Println(stage, m.Sys/1024/1024)
}

func main() {
    printMemStats("before")
    a := make([]uint64, 1000000000)
    printMemStats("after")
    a = nil
    runtime.GC()
    debug.FreeOSMemory()
    printMemStats("remove")
    _ = a // get rid of the unused variable error
}

That results in:

before 68
after 7997
remove 7998

Whereas the expected output is:

before 68
after 7997
remove 68
Alex S.
  • 315
  • 3
  • 12
  • 1
    You should use `m.Alloc`, not `m.Sys`. – tkausl Mar 21 '21 at 17:55
  • Yes, but the system memory is not released. It takes as much memory at the end as it was taking after the memory allocation. – Alex S. Mar 21 '21 at 17:59
  • Allocating and freeing memory from the OS is expensive. It would be a waste of time to give memory back to the os each time something is free'd, since it'd be allocated again right away when the program needs some memory again. – tkausl Mar 21 '21 at 18:01
  • It is, but in my case, the slice takes the majority of the system memory. I need to deallocate it to allocate a new one with a slight difference in size. – Alex S. Mar 21 '21 at 18:03
  • 3
    You _did_ deallocate it and Golang will use this free memory for the next allocation. – tkausl Mar 21 '21 at 18:04
  • You simply cannot control this the way you want. If this is a real requirement (I doupt it): use C. – Volker Mar 21 '21 at 18:05
  • Even when the memory scavenger marks memory as free, the OS is not required to reclaim it, and often won’t until under pressure to do so. – JimB Mar 21 '21 at 18:13
  • 2
    It might be better to pose the original problem that lead you to believe that you need to free the memory to the OS. – Hymns For Disco Mar 21 '21 at 18:22
  • @tkausl is right. Memory was deallocated inside Go but not inside the OS. What happened is that my program started to allocate a new slice even before the first one was GC'ed, and this caused the memory to hold 2x objects at once. Hence, the m.Sys tricked me into thinking that Go has not cleared the memory after the first object. – Alex S. Mar 21 '21 at 18:49

1 Answers1

4

First of all, you should really use debug.FreeOSMemory() only in extreme exception cases. Go is manages memory and thus you cannot control the behavior the same way you would be able to do it in C/C++.

The official documentation states:

return as much memory to the operating system as possible.

This does not guarantee that it will always return everything immediately as memory allocation is expensive and it would be not prudent to minimize memory footprint with complete disregard of performance. This post explains more things in detail why you should not use it in a production setting.

NeatNerd
  • 2,305
  • 3
  • 26
  • 49