Ответ
Аллокатор памяти (Memory Allocator) в Go — это часть рантайма (runtime), которая отвечает за управление динамической памятью в куче (heap). Его главная задача — быстро и эффективно выделять и освобождать память для объектов, минимизируя при этом фрагментацию и задержки, связанные с блокировками.
Ключевые цели аллокатора в Go:
- Скорость: Выделение памяти должно быть очень быстрым.
- Эффективность: Минимизация неиспользуемой, но выделенной памяти (фрагментации).
- Масштабируемость: Хорошая работа в многопоточных приложениях с минимальными блокировками.
Основные компоненты архитектуры:
mspan
(Memory Span): Базовый блок управления памятью. Это непрерывный участок виртуальной памяти, который делится на страницы (8KB) и может содержать объекты одного размера (size class).mcache
(Memory Cache): Локальный кеш памяти для каждой горутины (точнее, для каждого системного потокаP
). Он содержитmspan
-ы для объектов разных размеров. Посколькуmcache
локален для потока, выделение памяти из него происходит без блокировок, что очень быстро.mcentral
(Memory Central): Глобальный кешmspan
-ов для определённого класса размеров. Когда уmcache
заканчиваются свободные слоты, он запрашивает новыйmspan
уmcentral
. Доступ кmcentral
требует блокировки.mheap
(Memory Heap): Главный управляющий кучей. Он владеет всемиmspan
-ами. Если вmcentral
нет свободныхmspan
-ов, он запрашивает новую порцию памяти уmheap
.mheap
, в свою очередь, при необходимости запрашивает память у операционной системы.
Процесс выделения памяти:
// go:noinline
func createObject() *int {
p := new(int) // Аллокатор попытается выделить память
return p
}
- Escape Analysis: Компилятор определяет, может ли объект жить на стеке. Если объект "сбегает" (например, возвращается из функции по указателю), он должен быть размещён в куче.
- Выделение в куче: Аллокатор сначала ищет свободное место в
mcache
. Если его нет, он обращается кmcentral
, а затем, если нужно, кmheap
.
Аллокатор тесно работает со сборщиком мусора (GC), который находит и освобождает неиспользуемые объекты, возвращая память обратно в mspan
-ы для повторного использования.