Несколько раз вы могли бы захотеть избежать/свести к минимуму сборщик мусора, поэтому я хочу быть уверенным, как это сделать.
Я думаю, что следующий правильный:
- Объявить переменные в начале функции.
- Использовать массив вместо среза.
Больше?
Несколько раз вы могли бы захотеть избежать/свести к минимуму сборщик мусора, поэтому я хочу быть уверенным, как это сделать.
Я думаю, что следующий правильный:
Больше?
Избегать мусора относительно прямо. Вам нужно понять, где делаются ассигнования, и посмотреть, можно ли избежать выделения.
Во-первых, объявление переменных в начале функции НЕ поможет. Компилятор не знает разницы. Тем не менее, человек будет знать разницу, и это будет раздражать их.
Использование массива вместо среза будет работать, но это связано с тем, что в стек помещаются массивы (если не разыменовываются). Массивы имеют другие проблемы, такие как тот факт, что они передаются по значению (копируются) между функциями. Все, что в стеке, "не мусор", поскольку оно будет освобождено при возврате функции. Любой указатель или срез, который может выйти из функции, помещается в кучу, с которой сборщик мусора должен иметь дело в какой-то момент.
Лучшее, что вы можете сделать, это избежать выделения. Когда вы закончите с большими битами данных, которые вам не нужны, используйте их повторно. Это метод, используемый в профилировании в блоге Go. Я предлагаю прочитать его.
Другой пример, кроме примера в учебнике профилирования: Допустим, у вас есть фрагмент типа []int
с именем xs
. Вы постоянно добавляете к []int
, пока не достигнете условия, а затем вы reset, чтобы вы могли начать все заново. Если вы выполняете xs = nil
, вы теперь объявляете базовый массив среза как сборку мусора. Затем Append перераспределяет xs при следующем использовании. Если вместо этого вы выполняете xs = xs[:0]
, вы все равно перезагружаете его, но сохраняете старый массив.
По большей части, попытка избежать мусора - преждевременная оптимизация. Для большей части вашего кода это не имеет значения. Но вы можете найти время от времени функцию, которая называется много раз, которая выделяет много при каждом запуске. Или цикл, в котором вы перераспределяете вместо повторного использования. Я подожду, пока ты не увидишь горло бутылки перед тем, как отправиться за борт.
Чтобы минимизировать сбор мусора в Go, вы должны минимизировать распределение кучи. Чтобы минимизировать распределение кучи, вы должны понимать, когда происходит распределение.
Следующие вещи всегда вызывают распределения (по крайней мере, в компиляторе gc по адресу Go 1):
new
make
(за исключением нескольких маловероятных угловых случаев)&
string
, []byte
и []rune
m[string(b)]
, где m
- это карта, а b
- это []byte
string
defer
go
В зависимости от деталей следующие причины могут вызывать распределения:
a.b()
может принимать адрес a
, если a
не является указателем, а метод b
имеет тип приемника указателя.append
Список должен быть полным, и я в этом уверен, но с удовольствием рассмотрю дополнения или исправления.
Если вы не уверены в том, где происходят ваши распределения, вы всегда можете профилировать, как предложили другие, или посмотреть на сборку, создаваемую компилятором.