释放结构图

时间:2019-06-23 22:26:10

标签: go

我正在处理一个非常大的struct指针映射。它在程序的生命周期中不断增长(我将其用作缓冲区),并且编写了一个函数,该函数应在调用时减小其大小。

type S struct {
 a uint32
 b []uint32
}

s := make(map[uint32]*S)

for k, v := range s {
  delete(s, k)
  s[k] = &S{a: v.a}
}

我从映射的每个元素中删除了b,所以我期望内存中映射的大小会缩小(b是长度> 10的切片)。但是,内存没有释放,为什么?

2 个答案:

答案 0 :(得分:1)

映射值&S(即指针)的大小与切片b的容量无关。

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并将lencap设置为零。先前由基础array占用的内存将返回到垃圾回收器以供重用。

答案 1 :(得分:1)

地图大小限制为它在任何时候的最大大小。因为您存储的是指针(map [uint32] * S)而不是值,所以删除的对象最终会被垃圾回收,但通常不会立即被回收,这就是为什么您无法在监视器等top / htop中看到它的原因。

如果系统没有压力或资源不足,则运行时足够聪明,并保留内存以供将来使用。

请参阅https://stackoverflow.com/a/49963553/1199408,以了解有关内存的更多信息。

在您的示例中,您不需要调用delete。只需清除结构中的切片即可实现所需的功能。

type S struct {
 a uint32
 b []uint32
}

s := make(map[uint32]*S)

for k, v := range s {
  v.b = []uint32{}
}