增长切片时扩展内存(逻辑增长底层数组的容量)

Extend memory when grow slice (logic grow capacity underlying array)

我知道(并在互联网上阅读 - 包括此资源)。增加内存的逻辑是:if len array less than 1024 - golang multiply array on 2 else multiply len on 1.25(我们在源代码中看到这个毫无疑问https://github.com/golang/go/blob/cb2353deb74ecc1ca2105be44881c5d563a00fb8/src/runtime/slice.go#L95) 但是如果我在循环中填充切片,我会看到这种行为

t := []int{}
z := 0
for i := 1; i < 10000; i++ {
    t = append(t, i)

    if z < cap(t) {
        z = cap(t)
        fmt.Println(" len - ", len(t), " : cap - ", cap(t))
    }
}

len a.k.a。数

len -  1  : cap -  1
len -  2  : cap -  2
len -  3  : cap -  4
len -  5  : cap -  8
len -  9  : cap -  16
len -  17  : cap -  32
len -  33  : cap -  64
len -  65  : cap -  128
len -  129  : cap -  256
len -  257  : cap -  512
len -  513  : cap -  1024
len -  1025  : cap -  1280
len -  1281  : cap -  1696
len -  1697  : cap -  2304
len -  2305  : cap -  3072
len -  3073  : cap -  4096
len -  4097  : cap -  5120
len -  5121  : cap -  7168
len -  7169  : cap -  9216
len -  9217  : cap -  12288

before len 513 - capacity grow x2
len 1025 = 1.25 * len 513 = 1280 - capacity grow x1.25 (ok)
next capacity 1280*1.25 = 1600, but i see 1696 (len 1281).


Why difference = 96?


len 1281 - 3073 wrong, but len 3073 * 1.25 = 5120 (len 4097)

如果golang在增加slice时可以增加数组容量,那么当引用它的slice太小时它是否可以减少数组?

谢谢!

next capacity 1280*1.25 = 1600, but i see 1696 (len 1281).


src/runtime/malloc.go

// Small allocation sizes (up to and including 32 kB) are
// rounded to one of about 70 size classes, each of which
// has its own free set of objects of exactly that size.

growslice 请求最小分配大小。 mallocgc 执行分配。 mallocgc四舍五入到 class 大小以最小化碎片。


写一个收缩内存函数。

package main

import "fmt"

func shrink(s []byte) []byte {
    if (cap(s)-len(s))/len(s) >= 1 {
        t := s
        s = make([]byte, len(s), 2*len(s))
        copy(s, t)
    }
    return s
}

func main() {
    s := make([]byte, 32, 256)
    fmt.Println(len(s), cap(s))
    s = shrink(s)
    fmt.Println(len(s), cap(s))
}

游乐场:https://play.golang.org/p/udAEBJ-kWQ9

输出:

32 256
32 64

如您所见,它会耗费时间和内存。只有您可以决定在您的特定情况下是否值得。