Некоторые обычно выделяемые элементы в ядре, такие, как структуры процессов, потоков, vnode и управляющих блоков, недостаточно хорошо обрабатываются интерфейсом malloc общего назначения. У этих структур есть несколько общих характеристик.
Они имеют тенденцию быть большими и, следовательно, неэкономными по объему. Например, структура процесса занимает примерно 550 байт, которые при округлении до размера степени 2 требуют 1024 байта памяти.
Они имеют тенденцию быть часто используемыми. Поскольку они по отдельности не экономны, вместе они тратят значительно больше пространства по сравнению с более тесным представлением.
Они часто связаны вместе в длинные списки. Если выделение каждой структуры начинается на границе страницы, указатели списков все будут по одному и тому же смещению с начала страницы. При прохождении этих структур связывающие указатели все будут расположены в одной и той же строке аппаратного кеша, вызывая на каждом шаге по списку промах кеша, что замедляет прохождение списка.
Эти структуры часто содержат множество списков и блокировок, которые должны быть до использования инициализированы. Если для каждой структуры имеется выделенный пул памяти, эти подструктуры нужно инициализировать, лишь когда пул создается впервые, а не после каждого выделения.
По этим причинам FreeBSD предоставляет зональный распределитель (zone allocator). Зональный распределитель предоставляет эффективный интерфейс для управления набором элементов одного размера и типа. Создание различных зон ведет счетчик в стремлении сохранить всю память в одном пуле, чтобы максимизировать эффективность использования. Однако преимущества отделения памяти для небольшого набора структур, для которых подходит зональный распределитель, превосходит выигрыш в эффективности от сохранения их в общем пуле. Зональный распределитель минимизирует влияние отдельных пулов, освобождая память из зоны на основе снижения требований для объектов из области и при уведомлении о недостатке памяти демоном удаления страниц.
Зона является наращиваемым набором элементов одного размера. Зональный распределитель отслеживает активные и свободные элементы и предоставляет функции для выделения из зоны элементов и для обратного их освобождения, чтобы сделать доступными для последующего использования. Память выделяется для зоны по мере необходимости.
У элементов пула постоянный тип. Память в пуле не будет использоваться для каких-нибудь других целей. Структуру в пуле нужно инициализировать лишь при первом использовании. При последующем использовании можно считать, что инициализированные значения сохранят свое содержание, как при предыдущем освобождении. Предоставляется функция обратного вызова до освобождения памяти из области, чтобы подчистить любое сохраненное состояние.
Новая область создается функцией uma_zcreate(). Она должна указать размер выделяемых элементов и зарегистрировать два набора функций. Первый набор вызывается каждый раз при выделении или освобождении из области элемента. Они обычно отслеживают число выделенных элементов. Второй набор вызывается каждый раз при выделении или освобождении памяти из зоны. Они предоставляют ловушки для инициализации или разрушения подструктур внутри элементов, таких, как блокировки или мьютексы, когда они выделяются впервые или готовы к освобождению.
Элементы выделяются посредством uma_zalloc(), которая принимает идентификатор зоны, возвращенный uma_zcreate(). Элементы освобождаются с помощью uma_zfree(), которая принимает идентификатор зоны и указатель на освобождаемый элемент. При выделении или освобождении размер не требуется, поскольку размер элемента был установлен при создании зоны.
Чтобы способствовать повышению производительности на многопроцессорных системах, зона может поддерживаться страницами из кешей каждого из процессоров для объектов, которые могут иметь процессорное притяжение (affinity). Например, если ожидается, что определенный процесс будет запускаться на одном и том же процессоре, было бы целесообразно выделять его структуры из кеша для этого процессора.
Зональный распределитель предоставляет функцию uma_zone_set_max() для установки верхнего предела элементов в зоне. Предел общего числа элементов в зоне включает выделенные и свободные элементы, включая элементы в кешах отдельных процессоров. На многопроцессорных системах может оказаться невозможным выделить новый элемент для определенного процессора, поскольку был достигнут предел и все свободные элементы находятся в кешах других процессоров.
- 28/10/2010 11:59 - Раскраска страниц (page coloring)
- 28/10/2010 08:07 - Манипулирование процесса своим адресным пространством
- 26/10/2010 13:51 - Исполнение файла
- 26/10/2010 11:57 - Дизайн аппаратного кеша
- 26/10/2010 07:21 - Дублирование адресного пространства пользователя
- 25/10/2010 16:31 - Создание нового процесса
- 24/10/2010 06:47 - Индивидуальные моментальные снимки
- 23/10/2010 02:20 - Страничная подкачка
- 22/10/2010 23:00 - Пейджер подкачки
- 22/10/2010 12:25 - Сворачивание теневых цепочек