Публичный интерфейс модуля аллокатора-профилировщика для серверных очередей/пакетов
Подробнее...
Публичный интерфейс модуля аллокатора-профилировщика для серверных очередей/пакетов
- Автор
- felex67 (admin.nosp@m.@fel.nosp@m.exdev.nosp@m..ru)
- Версия
- 1.0.0 dev-in-progress
Language: C11 (ISO/IEC 9899:2011).
SRP + KISS + YAGNI + HLP(High Level Performance)
Лицензия: Apache 2.0
- Заметки
- Поддерживаемые компиляторы:
- MSVC: Версия >= 1930(VisualStudio 22+)
- GCC: Версия >= 5.0
- CLang: Любая поддерживающая C-11
- Предупреждения
- Изменять указатели
(*fxalloc)()/(*fxfree)() строго запрещено!!!
- Заметки
- Для увеличения производительности необходимо заключение контракта: определение макроса
_I_UNDERSTAND_THAT_I_SHOULD_NEVER_CHANGE_THESE_POINTERS_. Без определения этого макроса модуль вынужден работать через прокси-функции что влечёт за собой снижение производительности(увеличение ~25 тактов на вызов fxalloc/fxfree).
-
Режим
__FXALLOC_TURBO работает только при неконстантных fxalloc/fxfree. В этом режиме недоступен глубокий анализ использования памяти. Особенности:
- Метаданные для каждого блока уменьшаются до 16-ти байт.
- Все блоки выравниваются по адресам кратным 16.
- Все LIFO Грейдов выравниваются по L1(кэш процессора первого уровня). Настроить можно изменив
FXALLOC_LIFO_HEAD_ALIGN на соответствующее Вашей архитектуре значение
-
Первый вызов
fxalloc()(без предварительного вызова fxalloc_init()) в потоке/процессе крайне медленный так как происходит инициализация пула, для потока/процесса, последующие вызовы будут работать с инициализированным пулом памяти. Для преднастройки пула потока используйте функцию fxalloc_init().
-
Теоретический максимальный размер блока
(1U << 32) - 25 → 4'294'967'271 байт. Рекомендуемый размер блока не более 64 КиБ.
-
Профилированием и очисткой памяти потока занимается поток-наблюдатель, запускается при первом обращении к аллокатору и завершается только после очистки последнего пула, для обеспечения безаварийного завершения перед выходом из процесса используете fxalloc_finalize(). Пул потока освобождается только когда все блоки возвращены потоку-владельцу или при вызове fxalloc_finalize().
Алгоритмы использования:
void* ptr = fxalloc(N) → работаем с ptr → fxfree(ptr) → fxalloc_cleanup()
fxalloc → При первом вызове инициализирует пул в глобальной области с настройками по умолчанию для данного потока, вызывает malloc, устанавливает метаданные.
- Работа с указателем: Можно передавать в любой поток.
fxfree → анализ метаданных с последующим возвратом блока потоку-владельцу без вызова free(), блок остаётся в пуле.
fxalloc_cleanup() → Запускает процесс очищения памяти занятой потоком.
fxalloc_init(grades, threadName, FXSEARCH_...) → работаем → fxalloc_cleanup()
fxalloc_init → Инициализирует пул в глобальной области для данного потока с переданными настройками: FXGrade*, ThreadName, eXFAllocSearchType.
fxalloc_cleanup() → Запускает процесс очищения памяти занятой потоком. Такое поведение помогает собрать статистику для профилирования. Данные об использовании памяти могут быть получены переводом аллокатора в режим анализа(выполняется потоком-наблюдателем).
Рекомендации по использованию: Аллокатор в первую очередь рассчитан на рпофилирование с постепенным переходом в рабочий режим. Режимы профилирования можно переключать во время работы приложения как для конкретного потока(fxalloc_profile_thread), так и для всего приложения в целом(fxalloc_profile). Концепция использования:
- Проверка на критические ошибки в вызывающем коде без определения мкросов: На этом этапе отлавливаются все попытки изменить указатели
fxalloc и fxfree, попытки повторного высвобождения, а также передача "не родных" указателей(приложение моментально падает с SegmentationFault, создаётся файл fxalloc.log с текстовым описанием ошибки).
- Определение макроса
_I_UNDERSTAND_THAT_I_SHOULD_NEVER_CHANGE_THESE_POINTERS_: исключает работу аллокатора через прокси-функции первичные проверки первого этапа, подразумевается что этап 1 пройден. Требуется перекомпияция проекта после первого этапа. Вэтом режиме как и в предыдущем доступен режим глубокого профилирования.
- После первичных рабочих нагрузок и стабильной работы перекомпиляция проекта с определённым макросом __FXALLOC_TURBO. Максимально уменьшаются метаданные(до 16 байт, 2 указателя + выравнивание(если x86)), остаётся доступен только режим поверхностного анализа: блоков всего, праллоцированно и выделено дополнительно.
- Заметки
- Во всех режимах аллокатор работаетпо принципу LIFO на атомиках(без блокировок), все головы стеков выровнены по линии L1, адреса блоков и пользовательских данных кратны 16-ти.
Подробное описание процесса разработки интерфейса и аллокатора в целом можно найти в файле: neurox/ccpp/fxalloc/DIARY.md
Это перечисление устанавливает настройки аллокатора по умолчанию
FXALLOC_GRADE_STEP_SHIFT - шаг размера блоков, напрямую влияет на количество грейдов и суммарный размер метаданных всех гоейдов пула для каждого потока.
FXALLOC_LIFO_HEAD_ALIGN - настраивается для вашего процессора по размеру кеша L1. Значение по умолчанию 64. Действет на весь процесс, для изменения необходима рекомпиляция.
FXALLOC_MAX_GRADE_SIZE - Ограничитель максимаьного размера грейда Значение по умолчанию 0x10000 = 65'536 байт.
- Заметки
- Пример для FXALLOC_GRADE_STEP_SHIFT = 5, FXALLOC_MAX_GRADE_SIZE = 1024
- Шаг размера: (1 << 5) = 32 байта: [32, 64, 96, 128...]
- Количество грейдов: 1024 / 32 = 32
| Элементы перечислений |
|---|
| FXALLOC_GRADE_STEP_SHIFT | Количество сдвигов определяющее шаг размера блока: (1 << 6) = 64
Значение по умолчанию: 6.
|
| FXALLOC_LIFO_HEAD_ALIGN | Выравние головы стека свободных блоков по линии кеша L1
Значение по умолчанию: 64.
|
| FXALLOC_MAX_GRADE_SIZE | Ограничитель максимаьного размера блока
Значение по умолчанию: 65'536 байт.
|