Go 结构的释放映射

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

我正在使用指向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
的大小都是相同的

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占用的内存。