эффективно хранить коллекцию последних N отправленных элементов - PullRequest
0 голосов
/ 09 апреля 2019

Дано:

  1. ломтик с заранее известной емкостью
  2. Емкость и количество фрагментов велики, и будет использовано около 15 МБ памяти, поэтому я не хочу тратить впустую память и хочу сохранить минимальный объем памяти.
  3. Срез будет обновлен путем удаления первого элемента и добавления нового элемента в конец среза.

b = append(b[1:], n) увеличит емкость

чтобы сдвинуть и назначить себя, я написал

func shiftAndPut(a []int, n int) (b []int) {
    b = make([]int, cap(a), cap(a))
    for i,v := range(a[1:]) {
        b[i] = v
    }
    b[len(b)-1] = n
    return
}

https://play.golang.org/p/7xIBh0UPp2w

Он сохраняет емкость, но требует различных вычислений

  1. итерация среза один раз,
  2. вызов функции,
  3. новая переменная для малого времени,
  4. подрезка в функции диапазона, которая добавляет больше вычислений,
  5. и т.д.

Есть ли более оптимизированный способ сделать это?

1 Ответ

1 голос
/ 09 апреля 2019

Кольцевой буфер срезов, пользовательская реализация:

data := make([]int, cap, cap)
pointer := 0

data[pointer] = newData
pointer = (pointer+1) % cap

custom / ring Реализация пакета:

data := ring.New(cap)
data.Value = newData
data = data.Next()

После предложения в ветке комментариев я сделал тест между пользовательское смещение слайса и пользовательское / кольцо

BenchmarkCustom1000-4         100000         17322 ns/op
BenchmarkRing1000-4           100000         22824 ns/op
BenchmarkCustom-4           100000000           17.4 ns/op
BenchmarkRing-4             100000000           22.8 ns/op

пользовательское смещение слайса с использованием переменной (указатель или флаг) выполняется быстрее, а также оптимизируется память.

...