Иконка ресурса

Другое [INC] Dynamic memory (Heap) V1.1.0

Нет прав для скачивания
Поддерживаемые игры
CS: Source (OrangeBox), CS: GO, Team Fortress 2, DOD: Source, L4D 1 & 2
Поскольку SourcePawn не имеет реализации кучи (heap), для динамического выделения памяти, я создал свою.

Этот инклуд добавляет функции для создания и использования динамической памяти выделенной внутри плагина.
Выделение памяти делается на основе глобального одномерного массива.

О том как это работает, вы можете прочитать в соответствующем уроке:
"Организация кучи (динамической памяти) на основе одномерного статического массива"

Используемые понятия:
Двоичное дерево поиска (англ. binary search tree, BST)
Ячейка памяти (англ. cell, 4 байтная переменная любого типа)

Использование
PHP:
// Используйте эти определения до включения инклуда
#define HEAP_SIZE 16384 // Опциональное определение, переопределяет размер кучи; измеряется в ячейках
#define BST_ALLOC_COUNT 256 // Опциональное определение, переопределяет шаг выделения памяти для BST; измеряется в кол-ве узлов дерева
#define FREE_MEM_SLICE_MIN 8 // Опциональное определение, переопределяет лимит дробления памяти

#define DEBUG_HEAP_MEMORY_FULL // Добавьте это определение для включения всех проверок
#define DEBUG_HEAP_MEMORY_INIT // Добавьте это определение для включения проверки инициализации
#define DEBUG_HEAP_MEMORY_SIZE // Добавьте это определение для включения проверки указанных размеров
#define DEBUG_HEAP_MEMORY_BOUNDS // Добавьте это определение для включения проверки указанных адресов (осторожно, может замедлять работу чтения/записи в 1.5 раза)
#define DEBUG_HEAP_MEMORY_MAGIC // Добавьте это определение для включения проверки магического числа
#define DEBUG_HEAP_MEMORY_STATUS // Добавьте это определение для включения проверки статуса изменяемой памяти

// Используйте 0 в качестве нулевого указателя (адреса)
// Адреса представляют собой число больше нуля (индексы ячеек в массиве, от места где была выделена память)

int memalloc(int size);
void free(int adr);
int realloc(int adr, int size);

void store(int adr, any value);
any load(int adr);
void mempaste(int adr, const any[] array, int size);
void memcopy(int adr, any[] array, int size);
void memmove(int fromadr, int toadr, int size);
void memmover(int fromadr, int toadr, int size);
void mempastestr(int adr, const char[] str, int size);
void memcopystr(int adr, char[] str, int size);
Производительность
Замеры проводились на сервере CS:GO с 2-х ядерном процессором 2.66 ГГц каждое
Результаты представляют собой среднее 10-и замеров
Pawn:
0.001208 s for first alloc and free with initialization

0.000254 s for allocate 1000 blocks by 64 cells
0.000955 s for read 64000 cells
0.001092 s for write 64000 cells
0.000265 s for free 1000 blocks by 64 cells
Код для тестирования
PHP:
#include <profiler>

#define HEAP_SIZE 131072
#include <memory>

#define OBJECT_NUMBER 1000
#define OBJECT_SIZE 64

Handle prof;
int count = 10;

public void OnPluginStart()
{
    prof = CreateProfiler();
    StartProfiling(prof);
    free(memalloc(10));
    StopProfiling(prof);
    PrintToServer("%f s", GetProfilerTime(prof));

    Frame(0);
}

public void Frame(any data)
{
    count--;
    MakeProf();
    if (count != 0)
        RequestFrame(Frame);
}

void MakeProf()
{
    int blocks[OBJECT_NUMBER], i;
 
    int n, v;
    StartProfiling(prof);
    for (i = 0; i < OBJECT_NUMBER; i++)
    {
        blocks[i] = memalloc(OBJECT_SIZE);
    }
    StopProfiling(prof);
    PrintToServer("%f s for allocate %i blocks by %i cells", GetProfilerTime(prof), OBJECT_NUMBER, OBJECT_SIZE);
 
    StartProfiling(prof);
    for (i = 0; i < OBJECT_NUMBER; i++)
    {
        for (n = 0; n < OBJECT_SIZE; n++)
        {
            v = load(blocks[i] + n);
        }
    }
    StopProfiling(prof);
    PrintToServer("%f s for read %i cells", GetProfilerTime(prof), OBJECT_NUMBER * OBJECT_SIZE);
 
    StartProfiling(prof);
    for (i = 0; i < OBJECT_NUMBER; i++)
    {
        for (n = 0; n < OBJECT_SIZE; n++)
        {
            store(blocks[i] + n, v);
        }
    }
    StopProfiling(prof);
    PrintToServer("%f s for write %i cells", GetProfilerTime(prof), OBJECT_NUMBER * OBJECT_SIZE);
 
    StartProfiling(prof);
    for (i = 0; i < OBJECT_NUMBER; i++)
    {
        free(blocks[i]);
    }
    StopProfiling(prof);
    PrintToServer("%f s for free %i blocks by %i cells", GetProfilerTime(prof), OBJECT_NUMBER, OBJECT_SIZE);
}
Автор
Kailo
Скачиваний
40
Просмотры
1,260
Первый выпуск
Обновление
Оценка
5.00 звёзд 1 оценок

Другие ресурсы пользователя Kailo

Последние обновления

  1. Релиз 1.2.0!

    Балансировка: Красно-чёрное дерево
  2. Релиз 1.1.0!

    Добавлены функции для копирования строк.

Последние рецензии

Это же то, о чем я думаю? Кажется опять с ума сойду, читая это все. :D
Спасибо тебе, Кайло!
Сверху