go语言的map回收机制

在 Golang 中的 map 构造,在删除键值对的时候,并不会真正的删除,只是标记以后的key状态为empty。咱们上面的程序作为例子,看看当咱们在删除map中键值对时的内存变动,并理解如能力真正实现对键值对的垃圾回收。

程序根本流程为:在initMap()中,向map构造中插入10000对键值对,而后在全副删除,通过runtime.MemStats打印内存应用状况。

package mainimport (    "log"    "runtime")var lastFreed uint64type element struct {    X int    Y int}var EleMap map[int]*elementconst Num = 10000func main() {    printMemory()    runtime.GC()    initMap()    runtime.GC()    printMemory()    delMap()    runtime.GC()    printMemory()    EleMap = nil    runtime.GC()    printMemory()}func initMap() {    EleMap = make(map[int]*element)    for i := 0; i < Num; i++ {        EleMap[i] = &element{i * 2, i * 3}    }}func delMap() {    for i := 0; i < Num; i++ {        delete(EleMap, i)    }}func printMemory() {    var m runtime.MemStats    runtime.ReadMemStats(&m)    log.Printf("Alloc=%v||TotalAlloc=%v||Just_Freed=%v||Sys=%v||numGc=%v\n",        m.Alloc/1024, m.TotalAlloc/1024, ((m.TotalAlloc-m.Alloc)-lastFreed)/1024, m.Sys/1024, m.NumGC)    lastFreed = m.TotalAlloc - m.Alloc}

程序运行后果如下:

2022/02/09 22:38:38 Alloc=159||TotalAlloc=159||Just_Freed=0||Sys=8019||numGc=02022/02/09 22:38:38 Alloc=628||TotalAlloc=991||Just_Freed=362||Sys=8658||numGc=22022/02/09 22:38:38 Alloc=474||TotalAlloc=993||Just_Freed=156||Sys=8658||numGc=32022/02/09 22:38:38 Alloc=162||TotalAlloc=994||Just_Freed=313||Sys=8914||numGc=4

通过第三行日志能够看出,当咱们删除所有的键值对,并执行垃圾回收之后,以后调配的内存为474,而非初始状态的内存159。能够看出有相当一部分内存并没有被回收。因而删除键值对并不能保障背地的内存也被回收。

在某些零碎中,map会作为缓存来存储数据,即便依照超时工夫,定期删除某些键值对,也难以保障缓存占用的内存会被开释,会导致系统有内存透露的危险。