Memory Slices

Memory Slices — Эффективный способ распределения групп эквивалентных по размеру участков памяти.

Краткое описание

#include <glib.h> gpointer g_slice_alloc (gsize block_size); gpointer g_slice_alloc0 (gsize block_size); void g_slice_free1 (gsize block_size, gpointer mem_block); void g_slice_free_chain_with_offset (gsize block_size, gpointer mem_chain, gsize next_offset); #define g_slice_new (type) #define g_slice_new0 (type) #define g_slice_free (type, mem) #define g_slice_free_chain (type, mem_chain, next)

Описание

Слайсы памяти обеспечивают пространственно-эффективный и многопроцессорно-масштабируемый путь для распределения равных по размеру частей памяти, так же как оригинальный GMemChunks (from GLib <= 2.8), избегая чрезмерной траты памяти, потери масштабируемости и проблем выполнения.

Для достижения этих целей, распределитель слайсов использует сложный, многоуровневый дизайн который был создан благодаря распределителю слайсов Bonwick's [5]. Он использует posix_memalign() для оптимизированного распределения множества участков одинакового размера и имеет посредством потока свободные списки (так называемый уровень журналирования) для быстрого удовлетворения запросов распределения уже известных размеров структур. Это сопровождается дополнительным логическим кэшированием, чтобы иметь свободную память в течении некоторого времени перед возвращением в систему. Память которая не используется из-за ограничений выравнивания, используется для колоризации кэша (произвольное распределение адресов участка) для улучшенного использования кэша CPU. Кэширующий уровень распределителя слайсов самостоятельно адаптируется к высокой конкуренции блокирования для улучшения масштабируемости.

Распределитель слайсов может распределять небольшие блоки в два указателя, и в отличие от malloc(), он не резервирует дополнительное пространство в блоке. Для блоков большого размера, g_slice_new() и g_slice_alloc() автоматически делегируют к системной реализации malloc(). Для вновь создаваемого кода рекомендуется использовать новый g_slice API вместо g_malloc() и подобных, пока объекты не изменяют размер в течении их жизненного цикла и размер объекта используемый во время распределения остаётся доступным когда освобождается.

Пример 1. Использование распределителя слайсов

gchar *mem[10000]; gint i; /* Распределяем 10000 блоков. */ for (i = 0; i < 10000; i++) { mem[i] = g_slice_alloc (50); /* Fill in the memory with some junk. */ for (j = 0; j < 50; j++) mem[i][j] = i * j; } /* Освобождаем все блоки. */ for (i = 0; i < 10000; i++) { g_slice_free1 (50, mem[i]); }

Пример 2. Использование распределителя слайсов со структурами данных

GRealArray *array; /* Распределяем один блок, используя макрос g_slice_new(). */ array = g_slice_new (GRealArray); /* Теперь мы можем использовать массив как обычный указатель на структуру. */ array->data = NULL; array->len = 0; array->alloc = 0; array->zero_terminated = (zero_terminated ? 1 : 0); array->clear = (clear ? 1 : 0); array->elt_size = elt_size; /* Мы можем освобождать блок, поэтому он может использоваться многократно. */ g_slice_free (GRealArray, array);

Детали

g_slice_alloc ()

gpointer g_slice_alloc (gsize block_size);

Распределяет блок памяти из распределителя слайсов. Адрес полученного блока, как гарантируется, будет выравнен по крайней мере 2 * sizeof (void*). Помните что основной механизм распределения слайсов может быть изменён с помощью переменной окружения G_SLICE=always-malloc.

block_size : количество байт для распределения
Возвращает : указатель на распределённую память block

Начиная с версии 2.10


g_slice_alloc0 ()

gpointer g_slice_alloc0 (gsize block_size);

Распределяет блок памяти через g_slice_alloc() и инициализирует возвращаемую память 0. Помните что основной механизм распределения слайсов может быть изменён с помощью переменной окружения G_SLICE=always-malloc.

block_size : количество байт для распределения
Возвращает : указатель на распределённый блок

Начиная с версии 2.10


g_slice_free1 ()

void g_slice_free1 (gsize block_size, gpointer mem_block);

Освобождает блок памяти. Память должна быть распределена через g_slice_alloc() или g_slice_alloc0(), а block_size должен соответствовать размеру определённому при распределении. Помните что существующее поведение может быть изменено с помощью переменной окружения G_DEBUG=gc-friendly.

block_size : размер блока
mem_block : указатель на блок для освобождения

Начиная с версии 2.10


g_slice_free_chain_with_offset ()

void g_slice_free_chain_with_offset (gsize block_size, gpointer mem_chain, gsize next_offset);

Освобождает связанный список блоков памяти структуры имеющей тип type. Блоки памяти должны быть одинакового размера, распределённые через g_slice_alloc() или g_slice_alloc0() и связаны вместе указателем next (также как в GSList). Смещение поля next передаётся в каждый блок как третий аргумент. Помните что существующее поведение может быть изменено с помощью переменной окружения G_DEBUG=gc-friendly.

block_size : размер блоков
mem_chain : указатель на первый блок в цепочке
next_offset : поле смещения next в блоках

Начиная с версии 2.10


g_slice_new()

#define g_slice_new(type)

Удобный макрос для распределения блоков памяти из распределителя слайсов. Он вызывает g_slice_alloc() с sizeof (type) и приводит возвращаемый указатель к указателю данного типа, избегая приведения типа в исходном коде. Помните что основной механизм распределения слайсов может быть изменён с помощью переменной окружения G_SLICE=always-malloc.

type : тип для распределения, обычно имя структуры
Возвращает : указатель на распределённый блок, приведённый к указателю type.

Начиная с версии 2.10


g_slice_new0()

#define g_slice_new0(type)

Удобный макрос для распределения блока памяти из распределителя слайсов и установки памяти в 0. Он вызывает g_slice_alloc0() с sizeof (type) и приводит возвращаемый указатель к указателю полученного типа, избегая приведения указателя в исходном коде. Помните что основной механизм распределения слайсов может быть изменён с помощью переменной окружения G_SLICE=always-malloc.

type : тип для распределения, обычно имя структуры
Возвращает : указатель на распределённый блок, приведённый к указателю type.

Начиная с версии 2.10


g_slice_free()

#define g_slice_free(type, mem)

Удобный макрос для освобождения блока памяти который был распределён из распределителя слайсов. Он вызывает g_slice_free1() используя sizeof (type) как размер блока. Помните что существующее поведение может быть изменено с помощью переменной окружения G_DEBUG=gc-friendly.

type : тип блока для освобождения, обычно имя структуры
mem : указатель на блок для освобождения

Начиная с версии 2.10


g_slice_free_chain()

#define g_slice_free_chain(type, mem_chain, next)

Освобождает связанный список блоков памяти структуры имеющей тип type. Блоки памяти должны быть одинакового размера, распределены через g_slice_alloc() или g_slice_alloc0() и связаны вместе указателем next (так же как в GSList). Имя поля next в type помещают как третий аргумент. Помните что существующее поведение может быть изменено с помощью переменной окружения G_DEBUG=gc-friendly.

type : тип mem_chain блоков
mem_chain : указатель на первый блок цепочки
next : имя поля следующего указателя в type

Начиная с версии 2.10



[5] [Bonwick94] Jeff Bonwick, The slab allocator: Кэширующий объекты распределитель памяти ядра. USENIX 1994, и [Bonwick01] Bonwick and Jonathan Adams, Magazines and vmem: Расширенное распределение слайсов для множества процессоров и произвольных ресурсов. USENIX 2001