我的代码中有一个map[string]string
。键由NewUUID()
之类的函数生成为随机字符串。一次,我发现程序运行了很长时间后,内存一直保持较高的水平。 pprof显示大多数(使用中)分配发生在函数NewUUID()
上。我认为这可能是由此地图引起的:条目被频繁插入和删除。
我看到一些结论说,当从映射中删除密钥时,该密钥实际上并未释放,而是设置了一个空标志。像这些问题一样:
Is it safe to remove selected keys from map within a range loop? Do I need to set a map to nil in order for it to be garbage collected?
但是当我深入研究runtime / map_faststr.go中的代码时(go版本:1.12),我发现似乎情况并非如此。该键被分配为nil,并且该值通过{{ 1}}或memclrHasPointers
。
那么哪个结论是正确的?删除键后地图会缩小吗?
memclrNoHeapPointers
的源代码在runtime / map_faststr.go中
map
如果真的释放了密钥,我的代码有什么问题?最小代码如下:
for ; b != nil; b = b.overflow(t) {
for i, kptr := uintptr(0), b.keys(); i < bucketCnt; i, kptr = i+1, add(kptr, 2*sys.PtrSize) {
k := (*stringStruct)(kptr)
if k.len != key.len || b.tophash[i] != top {
continue
}
if k.str != key.str && !memequal(k.str, key.str, uintptr(key.len)) {
continue
}
// Clear key's pointer.
k.str = nil // seams it would be released by GC
v := add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+i*uintptr(t.valuesize))
if t.elem.kind&kindNoPointers == 0 { // What kindNoPointers means?
memclrHasPointers(v, t.elem.size)
} else {
memclrNoHeapPointers(v, t.elem.size)
}
b.tophash[i] = emptyOne
...
}