NeurOX 1.0.0 dev-in-progress
Экосистема многопользовательской игры классические крестики-нолики с ИИ
Загрузка...
Поиск...
Не найдено
Файл FXAlloc.h

Публичный интерфейс модуля аллокатора-профилировщика для серверных очередей/пакетов Подробнее...

#include <stdint.h>
Граф включаемых заголовочных файлов для FXAlloc.h:
Граф файлов, в которые включается этот файл:

См. исходные тексты.

Классы

struct  FXGrade
 Структура преднастройки аллокатора задающая градации и количество блоков памяти. Массив должен быть отсортирован по возрастанию размера блока и заканчиваться элементом с est_size = 0 Поля: Подробнее...
 
struct  FXAllocSetupThread
 Структура настройки потока Подробнее...
 
struct  FXAllocGradeStat
 Структурная единица отчёта по каждому грейду Подробнее...
 
struct  FXAllocStatistics
 Структурная елиница отчёта по потокам Подробнее...
 

Перечисления

enum  eFXAllocDefaultConfig { FXALLOC_GRADE_STEP_SHIFT = 6 , FXALLOC_LIFO_HEAD_ALIGN = 64 , FXALLOC_MAX_GRADE_SIZE = 0x10000 }
 Это перечисление устанавливает настройки аллокатора по умолчанию Подробнее...
 
enum  eXFAllocSearchType { FXSEARCH_AUTO , FXSEARCH_LINEAR , FXSEARCH_BINARY , FXSEARCH_SHIFTED }
 Варианты настройки алгоритма поиска подходящего грейда для данного потока В случае если первой в потоке вызывается функция `fxalloc` режим автоматически устанавливается в сдвиговый, т.к. Инициализируется пул согласно `FXALLOC_GRADE_STEP_SHIFT` в своём алгоритме функции сдвигового поиска опираются именно на это значение. В противном случае(первый вызов - fxalloc_init) вы можете сами задать тип поиска. Рекомендации под задачу: Подробнее...
 
enum  eFXAllocProfile { FXALLOC_SPEED , FXALLOC_SUMMARY , FXALLOC_FULL , FXALLOC_GETPROFILE }
 Перечисление режимов работы аллокатора. Подробнее...
 

Функции

int fxalloc_init (FXAllocSetupThread *Options)
 Инициализирует локальный пул памяти исходя из заданных параметров блоков
 
void fxalloc_cleanup ()
 Высвобождает ресурсы занятые потоком. Вызывать непосредственно перед выходом из потока/процесса, в противном случае - UB или segfault
 
int fxalloc_profile (eFXAllocProfile Profile, void(*Callback)(FXAllocStatistics **MemoryState))
 Переключает режимы работы алокатора для всего роцесса
 
int fxalloc_profile_thread (int ThreadID, eFXAllocProfile Profile, void(*Callback)(FXAllocStatistics **MemoryState))
 Переключает режим работы алокатора для потока указанного в ThreadID.
 
void fxalloc_finalize ()
 Функция очистки всей занятой памяти.
 

Переменные

TLS void(*const fxalloc )(size_t NBytes)
 Указатель на функцию выделения памяти
 
TLS void(*const fxfree )(void *Ptr)
 Указатель на функцию высвобождения памяти выделенной исключительно fxalloc при использовании на любом другом указателе 100% неопределённое поведение
 

Подробное описание

Публичный интерфейс модуля аллокатора-профилировщика для серверных очередей/пакетов

Автор
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().

Алгоритмы использования:

  1. void* ptr = fxalloc(N) → работаем с ptr → fxfree(ptr)fxalloc_cleanup()
    • fxalloc → При первом вызове инициализирует пул в глобальной области с настройками по умолчанию для данного потока, вызывает malloc, устанавливает метаданные.
    • Работа с указателем: Можно передавать в любой поток.
    • fxfree → анализ метаданных с последующим возвратом блока потоку-владельцу без вызова free(), блок остаётся в пуле.
    • fxalloc_cleanup() → Запускает процесс очищения памяти занятой потоком.
  2. fxalloc_init(grades, threadName, FXSEARCH_...) → работаем → fxalloc_cleanup()
    • fxalloc_init → Инициализирует пул в глобальной области для данного потока с переданными настройками: FXGrade*, ThreadName, eXFAllocSearchType.
    • fxalloc_cleanup() → Запускает процесс очищения памяти занятой потоком. Такое поведение помогает собрать статистику для профилирования. Данные об использовании памяти могут быть получены переводом аллокатора в режим анализа(выполняется потоком-наблюдателем).

Рекомендации по использованию: Аллокатор в первую очередь рассчитан на рпофилирование с постепенным переходом в рабочий режим. Режимы профилирования можно переключать во время работы приложения как для конкретного потока(fxalloc_profile_thread), так и для всего приложения в целом(fxalloc_profile). Концепция использования:

  1. Проверка на критические ошибки в вызывающем коде без определения мкросов: На этом этапе отлавливаются все попытки изменить указатели fxalloc и fxfree, попытки повторного высвобождения, а также передача "не родных" указателей(приложение моментально падает с SegmentationFault, создаётся файл fxalloc.log с текстовым описанием ошибки).
  2. Определение макроса _I_UNDERSTAND_THAT_I_SHOULD_NEVER_CHANGE_THESE_POINTERS_: исключает работу аллокатора через прокси-функции первичные проверки первого этапа, подразумевается что этап 1 пройден. Требуется перекомпияция проекта после первого этапа. Вэтом режиме как и в предыдущем доступен режим глубокого профилирования.
  3. После первичных рабочих нагрузок и стабильной работы перекомпиляция проекта с определённым макросом __FXALLOC_TURBO. Максимально уменьшаются метаданные(до 16 байт, 2 указателя + выравнивание(если x86)), остаётся доступен только режим поверхностного анализа: блоков всего, праллоцированно и выделено дополнительно.
Заметки
Во всех режимах аллокатор работаетпо принципу LIFO на атомиках(без блокировок), все головы стеков выровнены по линии L1, адреса блоков и пользовательских данных кратны 16-ти. Подробное описание процесса разработки интерфейса и аллокатора в целом можно найти в файле: neurox/ccpp/fxalloc/DIARY.md

Перечисления

◆ eFXAllocDefaultConfig

Это перечисление устанавливает настройки аллокатора по умолчанию

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 байт.

◆ eFXAllocProfile

Перечисление режимов работы аллокатора.

Заметки
Подробное описание статистики в см. в описании структуры FXAllocGradeStat
Элементы перечислений
FXALLOC_SPEED 

Максимальная производительность без статистики

FXALLOC_SUMMARY 

Поверхностная статистика

FXALLOC_FULL 

Глубокий анализ расхода памяти

FXALLOC_GETPROFILE 

Используется для получения текущего профиля

◆ eXFAllocSearchType

Варианты настройки алгоритма поиска подходящего грейда для данного потока В случае если первой в потоке вызывается функция `fxalloc` режим автоматически устанавливается в сдвиговый, т.к. Инициализируется пул согласно `FXALLOC_GRADE_STEP_SHIFT` в своём алгоритме функции сдвигового поиска опираются именно на это значение. В противном случае(первый вызов - fxalloc_init) вы можете сами задать тип поиска. Рекомендации под задачу:

  • Высокая вариативность - оставить градации по умолчанию откалибровав FXALLOC_GRADE_STEP_SHIFT
  • Низкая вариативность(очереди) - линейный поиск
  • Средняя вариативность(запросы и т.д.) - бираный поиск
Элементы перечислений
FXSEARCH_AUTO 
FXSEARCH_LINEAR 

Выберется Бинарный/линейный в зависимости от длины массива градаций(>= 7)

FXSEARCH_BINARY 

Линейный поиск

FXSEARCH_SHIFTED 

Бинарный поиск

Функции

◆ fxalloc_cleanup()

void fxalloc_cleanup ( )

Высвобождает ресурсы занятые потоком. Вызывать непосредственно перед выходом из потока/процесса, в противном случае - UB или segfault

◆ fxalloc_finalize()

void fxalloc_finalize ( )

Функция очистки всей занятой памяти.

Предупреждения
Блокирующий вызов, должен быть вызван перед завершением процесса/приложения!

◆ fxalloc_init()

int fxalloc_init ( FXAllocSetupThread Options)

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

Заметки
Блокирующий вызов
Аргументы
[in]OptionsFXAllocSetupThread*: Указатель на структуру настроек.
Возвращает
int - внутренний идентификатор потока(порядковый номер), либо -1 в случае ошибки
Возвращаемые значения
(int)-1- Ошибка, данные сохраняются в errno(ENOMEM || EINVAL), описание ошибки можно получить используя strerror(errno)
(int)>=0 - порядковый номер потока использующего аллокатор FXAlloc

◆ fxalloc_profile()

int fxalloc_profile ( eFXAllocProfile  Profile,
void(*)(FXAllocStatistics **MemoryState)  Callback 
)

Переключает режимы работы алокатора для всего роцесса

Аргументы
ProfileeFXAllocProfile: режим профилирования FXALLOC_SPEED - Максимальная производительность без статистики FXALLOC_SUMMARY - Поверхностная статистика FXALLOC_FULL - Глубокий анализ расхода памяти
Callbackvoid(*)(FXAllocStatistics*): указатель на функцию-обработчик данных. При передаче NULL аргумент Profile будет проигнорирован.
MemoryStateFXAllocStatistics**: Массив указателей на статиистику для каждого грейда. Нулевой указатель в массиве обозначает конецмассива: MemoryState[N] == NULL. После обработки данных профилирования следует использовать free(MemoryState) для освобождения памяти.
Заметки
При Profile != FXALLOC_SPEED && Callback == NULL возвращает (int)0, errno устанавоивается в EINVAL
Возвращает
int
Возвращаемые значения
`1`при успешном переключении
`0`при ошибке, errno == EINVAL, описание strerror(errno).

◆ fxalloc_profile_thread()

int fxalloc_profile_thread ( int  ThreadID,
eFXAllocProfile  Profile,
void(*)(FXAllocStatistics **MemoryState)  Callback 
)

Переключает режим работы алокатора для потока указанного в ThreadID.

Аргументы
ThreadIDint: Внутренний идентификатор потока возвращённый функцией fxalloc_init()
ProfileeFXAllocProfile: режим профилирования FXALLOC_SPEED - Максимальная производительность без статистики FXALLOC_SUMMARY - Поверхностная статистика FXALLOC_FULL - Глубокий анализ расхода памяти
Callbackvoid(*)(FXAllocStatistics*): указатель на функцию-обработчик данных. При передаче NULL аргумент Profile будет проигнорирован.
MemoryStateFXAllocStatistics**: Массив указателей на статиистику для каждого грейда. Нулевой указатель в массиве обозначает конецмассива: MemoryState[N] == NULL. После обработки данных профилирования следует использовать free(MemoryState) для освобождения памяти.
Заметки
При Profile != FXALLOC_SPEED && Callback == NULL возвращает (int)0, errno устанавоивается в EINVAL
Возвращает
int
Возвращаемые значения
`1`при успешном переключении
`0`при ошибке, errno == EINVAL, описание strerror(errno).

Переменные

◆ fxalloc

TLS void(*const fxalloc) (size_t NBytes) ( size_t  NBytes)
extern

Указатель на функцию выделения памяти

Заметки
Ни в коем разе не должен изменяться из вызывающего кода!!!
Аргументы
[in]NBytessize_t - Количество байт
Возвращаемые значения
`!0`- С адресом кратным размеру sizeof(size_t). Указатель выровненный для любого типа данных
`NULL`- В случае единственно возможной ошибки ENOMEM результат сохранён в errno подробное описание strerror(errno)

◆ fxfree

TLS void(*const fxfree) (void *Ptr) ( void *  Ptr)
extern

Указатель на функцию высвобождения памяти выделенной исключительно fxalloc при использовании на любом другом указателе 100% неопределённое поведение

Заметки
Ни в коем разе не должен изменяться из вызывающего кода!!!
Аргументы
[in]Ptrvoid* - Указатель на блок памяти