Работа над дневником

This commit is contained in:
2026-05-05 03:13:47 +05:00
parent 51fa314d86
commit de3edc8486
12 changed files with 155 additions and 64 deletions
View File
+3
View File
@@ -0,0 +1,3 @@
{
"CurrentProjectSetting": "x64-Debug"
}
+15
View File
@@ -0,0 +1,15 @@
{
"OutputFoldersPerTargetSystem": {
"Local Machine": [
"out\\build\\x64-Debug",
"out\\install\\x64-Debug"
]
},
"ExpandedNodes": [
"",
"\\includes",
"\\src"
],
"SelectedNode": "\\src\\FXAlloc.c",
"PreviewInSolutionExplorer": false
}
Binary file not shown.
Binary file not shown.
+12
View File
@@ -0,0 +1,12 @@
{
"Version": 1,
"WorkspaceRootPath": "C:\\projects\\fullstack\\neurox\\ccpp\\fxalloc\\",
"Documents": [],
"DocumentGroupContainers": [
{
"Orientation": 0,
"VerticalTabListWidth": 256,
"DocumentGroups": []
}
]
}
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -1,4 +1,4 @@
cmake_minimal_required(VERSION 3.10) cmake_minimum_required(VERSION 3.15)
project(neurox) project(neurox)
set(SOURCES src/FXAlloc.c) set(SOURCES src/FXAlloc.c)
set(HEADERS headers/_FXAlloc.h) set(HEADERS headers/_FXAlloc.h)
+20 -1
View File
@@ -1100,6 +1100,25 @@ thread_local void* (*fxalloc)(size_t _NBytes);
thread_local void (*fxfree)(void* _Ptr); thread_local void (*fxfree)(void* _Ptr);
``` ```
Единственным узким местом остаётся переключение режимов, как это сделать расмотрим немного позже.
# 04.05.2026
Единственным узким местом остаётся переключение режимов, как это сделать расмотрим далее ## Переключение режимов работы:
Существенным недостатком использования TLS-указателей на функции является сложность их изменения во время работы из глобальной области. Но, опять таки, мы же пишем на С, будем использовать всю его мощь! Затратив памяти на 2 указателя в каждом отдельном пуле мы сможем обойти сложность TLS и спокойненько менять их по желанию, что имеется в виду:
```C
/* TLS-указатели на функции выделения и высвобождения памяти */
thread_local void* (*fxalloc)(size_t NBytes);
thread_local void (*fxfree)(void* Ptr);
/* Блок выделенный для конкретного потока в глобальном пуле */
typedef struct ThreadMemoryBlock {
void*(**fxalloc)(size_t); ///< Указатель на fxalloc потока
void(**fxfree)(void*); ///< Указатель на fxree потока
/* Остальные поля */
} ThreadMemoryBlock;
/* Управляющий поток-наблютель */
*(globalPoll.threads[tid].fxalloc) = fxalloc_summary;
*(globalPoll.threads[tid].fxfree) = fxfree_summary;
```
+95 -32
View File
@@ -1,47 +1,110 @@
#pragma once #pragma once
/**
* @file neurox/ccpp/fxalloc/includes/FXAlloc.h
* @author felex67 (admin@felexdev.ru)
* @version 1.0.0 beta
* @brief Публичный интерфейс модуля-аллокатора fxalloc(includes/FXAlloc.h)
*
* @details Language: C11 (ISO/IEC 9899:2011).
* Изначально аллокатор работает в следующем режиме:
* `fxalloc → выделение блока через malloc() с добавлением метаданных`,
* `fxfree → анализ метаданных с последующим вызовом free()`. Такое поведение
* помогает сборать статистику для профилирования, которые могут быть получены
* переводом аллокатора в режим анализа(выполняется потоком-наблюдателем).
* При необходимости выделения отдельного пула для потока используйте `fxalloc_init()`,
* в глобальном пуле(НЕ TLS!!!) будет выделен блок памяти для этого потока, что даст возможность
* передачи данных по очередям между потоками без повторных выделений, функция `fxfree()`
* из любого другого потока вернёт блок владельцу без накладных расходов на TLS, только
* атомарная синхронизация.\
* Изменение указателей `fxalloc` и `fxfree` строго запрещено! Без оперделения макроса
* `_I_UNDERSTAND_THE_RISKS_AND_ASSUME_RESPONSIBILITY_` возникнет ошибка компиляции.\
* По завершению работы потока/процесса в системах POSIX вся выделенная память
* освобождается автоматически, в Windows необходимо вызвать `fxalloc_cleanup()`.
* */
#include <stdint.h> #include <stdint.h>
#include <threads.h>
#ifndef _WIN32 #ifdef _WIN32 // Windows
#include <sys/types.h> #define thread_local __declspec(thread)
#else // Linux
#define thread_local __thread
#endif //_WIN32 #endif //_WIN32
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif //__cplusplus #endif //__cplusplus
/** /**
* @brief Структура преднастройки аллокатора задающая градации и количество блоков памяти * @brief Перечисление режимов работы аллокатора
* */
* @property +est_size: size_t - Предполагаемый размер блока typedef enum {
* @property +est_count: size_t - Предполагаемое количество блоков FXALLOC_SPEED, ///< Максимальная производительность без статистики
*/ FXALLOC_SUMMARY, ///< Поверхностная статистика
typedef struct FXGrade { FXALLOC_FULL ///< Глубокий анализ расхода памяти
/// Предполагаемый размер блока } eFXAllocProfile;
const size_t est_size;
/// Предполагаемое количество блоков
const size_t est_count;
} FXGrade;
/** /**
* @brief Переменная для сохранения преднастроек пула памяти с ноль-терминантом * @brief Структура преднастройки аллокатора задающая градации и количество блоков памяти.
* Определена в src/FXAlloc.c * Массив должен быть отсортирован по возрастанию размера блока
*/ * и заканчиваться элементом с `est_size = 0`
extern const FXGrade* grades; * @var +est_size: size_t - Предполагаемый размер блока
* @var +est_count: size_t - Предполагаемое количество блоков
*/
typedef struct FXGrade {
/// Предполагаемый размер блока
const size_t est_size;
/// Предполагаемое количество блоков
const size_t est_count;
} FXGrade;
/** /**
* @brief Функция выделения памяти * @brief Переключает режимы работы алокатора
* @param[in] _NBytes: size_t - Количество байт * FXALLOC_SPEED, ///< Максимальная производительность без статистики
* @retval !0 - Кратный size_t указатель выровненный для любого типа данных * FXALLOC_SUMMARY, ///< Поверхностная статистика
* @retval NULL - В случае единственно возможной ошибки EBADALLOC результат сохранён в errno * FXALLOC_FULL ///< Глубокий анализ расхода памяти
*/ * @retval !0 при успешном переключении
void* fxalloc(size_t _NBytes); * @retval 0 при ошибке(не вероятно)
*/
int fxalloc_profile(eFXAllocProfile Profile);
/** /**
* @brief Высвобождает память выделенную исключительно fxalloc * @brief Инициализирует локальный пулл памяти исходя из заданных параметров блоков
* @param[in] _Ptr: void* * @param[in] Grades: const FXGrade* - Указатель на массив градаций
*/ * @param[in] ThreadName: const char* - Наименование потока, используется при профилировании
void fxfree(void* _Ptr); * в следующем виде: `[thread_id] 'thread_name': blocks: total=1024 used=64...`.
* Если передан NULL - выводится только ID потока, т.е.: `[thread_id]: ...`
*/
int fxalloc_init(const FXGrade* Grades, const char* ThreadName);
/**
* @brief Указатель на функцию выделения памяти
* @note Ни в коем разе не должен изменяться из вызывающего кода!!!
* @param[in] NBytes: size_t - Количество байт
* @retval !0 - Кратный размеру(sizeof(size_t)) указатель выровненный для любого типа данных
* @retval NULL - В случае единственно возможной ошибки ENOMEM результат сохранён в errno
*/
#ifndef _I_UNDERSTAND_THE_RISKS_AND_ASSUME_RESPONSIBILITY_
extern thread_local void (*const fxalloc)(size_t NBytes);
#else
extern thread_local void (*fxalloc)(size_t NBytes);
#endif
/**
* @brief Указатель на функцию высвобождения памяти выделенной исключительно fxalloc
* при использовании на любом другом указателе 100% неопределённое поведение
* @note Ни в коем разе не должен изменяться из вызывающего кода!!!
* @param[in] _Ptr: void* - Указатель на блок памяти
*/
#ifndef _I_UNDERSTAND_THE_RISKS_AND_ASSUME_RESPONSIBILITY_
extern thread_local void (*const fxfree)(void* Ptr);
#else
extern thread_local void (*fxfree)(void* Ptr);
#endif
/**
* @brief Высвобождает ресурсы занятые потоком Вызывать непосредственно перед выходом,
* в противном случае UB или segfault
*/
void fxalloc_cleanup();
#ifdef __cplusplus #ifdef __cplusplus
} }
+9 -30
View File
@@ -1,36 +1,15 @@
#include <threads.h>
#include <Windows.h>
#include "FXAlloc.h" #include "FXAlloc.h"
#include <threads.h> void* fxalloc_local_init(size_t _NBytes);
// В этой переменной настраиваем градации и предположительное количесвто блоков void fxfree_prod(void* _Ptr);
static const FXGrade grades[] = { void fxfree_summ(void* _Ptr);
{ 32, 200 }, { 64, 200 }, { 128, 8000 }, void fxfree_prof(void* _Ptr);
{ 256, 4000 }, { 512, 2000 }, { 1024, 1200 },
{ 4096, 200 }, { 0x10000, 4 },
{ 0 } // Ноль-терминант
};
thread_local void* (*fxalloc)(size_t _NBytes) = fxalloc_local_init;
void (*fxfree)(void* _Ptr) = fxfree_prod;
#ifdef _WIN32
// Windows-версия
__declspec(thread) extern void* (*fxalloc)(size_t _NBytes);
__declspec(thread) extern void (*fxfree)(void* _Ptr);
#else
// POSIX-версия
extern static pthread_key_t thread_key;
extern void* (*fxalloc)(size_t _NBytes);
extern void (*fxfree)(void* _Ptr);
#endif
extern static pthread_key_t thread_key;
void* fastalloc(); void* fastalloc();
void init_tls() {
pthread_setspecific(thread_key, (void*)fxalloc);
fxalloc = fastalloc;
// или более сложный вариант с хранением структуры
}