Сделать размер ломтиков - PullRequest
0 голосов
/ 17 декабря 2018

В Golang вы можете выделить память для среза со следующим синтаксисом:

my_slice := make( []int, 0 )

А потом я могу добавить элементы со встроенной функцией добавления:

my_slice := append(my_slice, 23)

Мой вопрос: в чем разница между тем, чтобы дать этот ноль (или 2, или 5, или что-то еще) при «создании» среза, если в дальнейшем мы можем продолжать добавлять элементы, пока мы хотим?

Есть либонус производительности, пытаясь угадать емкость, которую в итоге получит срез?

Ответы [ 2 ]

0 голосов
/ 17 декабря 2018

Мой вопрос: в чем разница между тем, чтобы дать этот ноль (или 2, или 5, или что-то еще) при «создании» среза, если в дальнейшем мы сможем добавлять элементы до тех пор, пока мы хотим?

Неправильное распределение может привести к перераспределению.

Есть ли бонус производительности, если попытаться угадать, какой объем получит срез?

да, перераспределение приведет к дополнительному копированию на срезе.

Срез: Размер указывает длину.Емкость среза равна его длине.Второй целочисленный аргумент может быть предоставлен для указания другой емкости;оно должно быть не меньше длины.

Например, make ([] int, 0, 10) выделяет базовый массив размером 10 и возвращает фрагмент длиной 0 и емкостью 10, который поддерживается этим базовым массивом.

копия с go doc.

На мой взгляд.Slice как указатель с длиной и емкостью в c / c ++.Добавить к фрагменту добавит элементы после смещения по этому указателю.Емкость - это общий размер последовательного пространства.Если пространства capacity - allocated недостаточно, добавление приведет к перераспределению и копированию фрагмента.

make(s, 1)

go сделает больше, чем вы думаете:

  1. Выделите последовательный пробел больше, чем выдать (то же самое в векторе c ++), чтобы избежать перераспределения, которое может привести к низкой производительности.

  2. Инициализируйте размер, который вы даете в make.(RAII)

  3. Как только произойдет перераспределение, go выделит последовательное пространство в два раза больше и скопирует старый фрагмент в это место.Это также снизит производительность.

Чтобы избежать перераспределения, мы можем указать необязательные аргументы емкости в make, чтобы указать, что нам нужно больше места.

0 голосов
/ 17 декабря 2018

Разница в том, что память для среза выделяется авансом, а len(mySlice) возвращает общую длину среза.

В отношении производительности целесообразно выделять размер авансом, поскольку при вызове a = append(a, n) следующеепроисходит:

  • Вызывает встроенную функцию добавления и для этого сначала копирует срез a (заголовок слайса, резервный массив не является частью заголовка), и он должен создатьвременный срез для параметра переменной, который будет содержать значение n.

  • Затем он должен перекомпоновать a, если он имеет достаточную емкость, такую ​​как a = a[:len(a)+1] - что включает в себя назначениеновый фрагмент в a внутри функции добавления.Если у a недостаточно большой емкости, чтобы выполнить добавление «на месте», то должен быть выделен новый массив, скопировано содержимое из среза, а затем выполнено назначение / добавление.

  • Затем присваивает n [len(a)-1].

  • Затем возвращает новый срез из функции добавления, и этот новый срез назначается локальной переменной a.

По сравнению с a[i] = n, что является простым заданием.

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