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会作为缓存来存储数据,即便依照超时工夫,定期删除某些键值对,也难以保障缓存占用的内存会被开释,会导致系统有内存透露的危险。