Справочное описание GLib | ||||
---|---|---|---|---|
Memory SlicesMemory 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);
gpointer g_slice_alloc (gsize block_size);
Распределяет блок памяти из распределителя слайсов. Адрес полученного блока, как гарантируется, будет выравнен по крайней мере 2 * sizeof (void*). Помните что основной механизм распределения слайсов может быть изменён с помощью переменной окружения G_SLICE=always-malloc.
block_size : |
количество байт для распределения |
Возвращает : | указатель на распределённую память block |
Начиная с версии 2.10
gpointer g_slice_alloc0 (gsize block_size);
Распределяет блок памяти через g_slice_alloc()
и инициализирует возвращаемую память 0.
Помните что основной механизм распределения слайсов может быть изменён с помощью переменной окружения
G_SLICE=always-malloc.
block_size : |
количество байт для распределения |
Возвращает : | указатель на распределённый блок |
Начиная с версии 2.10
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
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
#define g_slice_new(type)
Удобный макрос для распределения блоков памяти из распределителя слайсов.
Он вызывает g_slice_alloc()
с
sizeof (type
) и приводит возвращаемый указатель к указателю данного типа,
избегая приведения типа в исходном коде.
Помните что основной механизм распределения слайсов может быть изменён с помощью переменной окружения
G_SLICE=always-malloc.
type : |
тип для распределения, обычно имя структуры |
Возвращает : | указатель на распределённый блок, приведённый к указателю type .
|
Начиная с версии 2.10
#define g_slice_new0(type)
Удобный макрос для распределения блока памяти из распределителя слайсов и установки памяти в 0.
Он вызывает g_slice_alloc0()
с sizeof (type
) и приводит возвращаемый указатель к указателю полученного типа,
избегая приведения указателя в исходном коде.
Помните что основной механизм распределения слайсов может быть изменён с помощью переменной окружения
G_SLICE=always-malloc.
type : |
тип для распределения, обычно имя структуры |
Возвращает : | указатель на распределённый блок, приведённый к указателю type .
|
Начиная с версии 2.10
#define g_slice_free(type, mem)
Удобный макрос для освобождения блока памяти который был распределён из распределителя слайсов.
Он вызывает g_slice_free1()
используя sizeof (type)
как размер блока.
Помните что существующее поведение может быть изменено с помощью переменной окружения
G_DEBUG=gc-friendly.
type : |
тип блока для освобождения, обычно имя структуры |
mem : |
указатель на блок для освобождения |
Начиная с версии 2.10
#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