Расширение памяти при увеличении среза (logi c увеличение емкости базового массива) - PullRequest
0 голосов
/ 10 января 2020

Я знаю (и читаю в inte rnet - включая этот ресурс). Что логика c для увеличения памяти такова: если массив len меньше 1024 - golang, умножьте массив на 2, умножьте len на 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 aka num

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 может увеличить массив емкости при увеличении среза, может ли он уменьшить массив, когда фрагмент, который ссылается на него, слишком мал?

Спасибо!

1 Ответ

1 голос
/ 10 января 2020

следующая емкость 1280 * 1,25 = 1600, но я вижу 1696 (len 1281).


src / runtime / mallo c. 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 округляется до размера класса, чтобы минимизировать фрагментацию.


Создать функцию сжатия памяти.

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

Как видите, это стоит времени и памяти. Только вы можете решить, стоит ли оно того в вашем конкретном случае.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...