Ответ
Эвакуация в map
в Go — это механизм постепенного (инкрементального) перераспределения данных из старых бакетов (buckets) в новые, который запускается при росте хэш-таблицы. Это позволяет избежать длительных пауз ("stop-the-world") при изменении размера map
.
Когда происходит эвакуация?
Процесс начинается, когда среднее количество элементов на один бакет (load factor) превышает 6.5.
Как происходит процесс?
- Аллокация новой таблицы: Создается новая, обычно в два раза большая, хэш-таблица.
- Постепенное копирование: Вместо того чтобы сразу копировать все данные, Go делает это постепенно. При каждой операции записи (а иногда и чтения) в
map
, один или два старых бакета "эвакуируются" — их содержимое переносится в новые бакеты. - Сосуществование: На время эвакуации старая и новая таблицы существуют одновременно. Операции чтения могут проверять оба набора бакетов.
- Завершение: Когда все данные из старых бакетов перенесены, старая таблица освобождается.
Пример, который может инициировать эвакуацию:
// Создаем map с начальной емкостью 8 бакетов
m := make(map[int]string)
// При добавлении элементов load factor будет расти.
// После добавления ~52 элементов (8 * 6.5), начнется эвакуация.
for i := 0; i < 100; i++ {
m[i] = fmt.Sprintf("value%d", i)
}
Ключевое преимущество: Эвакуация обеспечивает предсказуемую производительность, распределяя нагрузку по изменению размера map
во времени, что критически важно для систем с низкими задержками (low-latency).