Go 结构的释放映射
我正在使用指向struct的指针的一个非常大的映射。它在程序的生命周期中不断增长(我将其用作缓冲区),我编写了一个函数,该函数应该在调用它时减小它的大小Go 结构的释放映射,go,Go,我正在使用指向struct的指针的一个非常大的映射。它在程序的生命周期中不断增长(我将其用作缓冲区),我编写了一个函数,该函数应该在调用它时减小它的大小 类型S结构{ a uint32 b[]uint32 } s:=make(映射[uint32]*s) 对于k,v:=范围s{ 删除(s,k) s[k]=&s{a:v.a} } 我从映射的每个元素中删除b,因此我希望内存中映射的大小会缩小(b是长度大于10的切片)。但是内存没有释放,为什么?不管片b的容量如何,指针映射值&S的大小都是相同的 pa
类型S结构{
a uint32
b[]uint32
}
s:=make(映射[uint32]*s)
对于k,v:=范围s{
删除(s,k)
s[k]=&s{a:v.a}
}
我从映射的每个元素中删除
b
,因此我希望内存中映射的大小会缩小(b
是长度大于10的切片)。但是内存没有释放,为什么?不管片b
的容量如何,指针映射值&S
的大小都是相同的
package main
import (
"fmt"
"unsafe"
)
type S struct {
a uint32
b []uint32
}
func main() {
size := unsafe.Sizeof(&S{})
fmt.Println(size)
size = unsafe.Sizeof(&S{b: make([]uint32, 10)})
fmt.Println(size)
s := make(map[uint32]*S)
for k, v := range s {
delete(s, k)
s[k] = &S{a: v.a}
}
}
输出:
8
8
切片在内部由
type slice struct {
array unsafe.Pointer
len int
cap int
}
设置
&S{a:v.a}
时,将b
设置为初始值:array
设置为nil
和len
和cap
设置为零。以前由底层数组占用的内存将返回给垃圾收集器以供重用。映射大小将限制为其在任何点上的最大大小。因为存储指针(map[uint32]*S)而不是值,所以删除的对象最终会被垃圾回收,但通常不会立即被回收,这就是为什么在类似top/htop的监视器中看不到它的原因
运行时足够聪明,如果系统没有压力或资源不足,它会保留内存供将来使用
请参阅以了解有关内存的更多信息
在您的示例中,不需要调用delete。只需清除结构中的切片,即可实现所需
type S struct {
a uint32
b []uint32
}
s := make(map[uint32]*S)
for k, v := range s {
v.b = []uint32{}
}
一个切片的大小不是也被限制到了它的最大值吗?这就是我执行删除操作的原因:因此s
中切片的大小也是resetNo,因为它是指向结构实例的指针是,但我对全局内存使用情况感兴趣,而不仅仅是映射大小。因此,映射的每个元素都指向一个包含一个切片的结构。是的,删除的实例最终将被垃圾收集,但Go运行时可能不会立即将内存返回操作系统。v.b=v.b[:0]
释放零内存。切片仍然使用相同的底层数组。这只是意味着下一次添加切片时,切片不必再增长v.b:=[]uint32{}
实际上会释放内存。是的,对不起,在我的问题中,我说的是内存中的总大小(因此映射+到它指向的所有结构的大小)。您所描述的确实是我希望编写代码的行为。但是,垃圾收集器似乎不能释放/允许重用以前由strucs占用的内存。