perf(allocator): made medium allocations reusable by adding memory bin
This commit is contained in:
parent
120ddaed02
commit
21e79b8af4
2 changed files with 169 additions and 2 deletions
|
|
@ -25,11 +25,20 @@
|
|||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
|
||||
static const INIT_ONCE HALLOCY_INIT_ONCE = INIT_ONCE_STATIC_INIT;
|
||||
|
||||
static HANDLE hallocy_heap = NULL;
|
||||
static CRITICAL_SECTION hallocy_critical_section;
|
||||
#elif defined(__linux__)
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
#include <syscall.h>
|
||||
|
||||
static const int HALLOCY_FUTEX_WAKE = 0;
|
||||
static const int HALLOCY_FUTEX_WAIT = 1;
|
||||
|
||||
static int hallocy_futex_address = 0;
|
||||
#endif
|
||||
|
||||
typedef struct HallocyMemoryHeader {
|
||||
|
|
@ -37,12 +46,27 @@ typedef struct HallocyMemoryHeader {
|
|||
struct HallocyMemoryHeader *next;
|
||||
} HallocyMemoryHeader;
|
||||
|
||||
static size_t hallocy_medium_memory_freed = 0;
|
||||
static size_t hallocy_medium_memory_allocated = 0;
|
||||
static HallocyMemoryHeader *hallocy_medium_memory_bin = NULL;
|
||||
|
||||
static _Thread_local size_t hallocy_small_memory_freed = 0;
|
||||
static _Thread_local size_t hallocy_small_memory_allocated = 0;
|
||||
static _Thread_local HallocyMemoryHeader *hallocy_small_memory_bin = NULL;
|
||||
|
||||
static size_t page_size = 0;
|
||||
static size_t hallocy_small_allocation_size = 0;
|
||||
static size_t hallocy_medium_allocation_size = 0;
|
||||
|
||||
#if defined(_WIN32)
|
||||
static BOOL CALLBACK hallocy_initialize_mutex(PINIT_ONCE init_once, PVOID parameter, PVOID *context) {
|
||||
(void)init_once;
|
||||
(void)parameter;
|
||||
(void)context;
|
||||
|
||||
return InitializeCriticalSectionEx(&hallocy_critical_section, 0x00000400, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void *hallocy_malloc(size_t size) {
|
||||
if (page_size == 0) {
|
||||
|
|
@ -56,6 +80,7 @@ void *hallocy_malloc(size_t size) {
|
|||
#endif
|
||||
|
||||
hallocy_small_allocation_size = page_size;
|
||||
hallocy_medium_allocation_size = page_size * 10;
|
||||
}
|
||||
|
||||
size_t aligned_size = page_size * (((size + sizeof(HallocyMemoryHeader)) / page_size) + 1);
|
||||
|
|
@ -99,6 +124,72 @@ void *hallocy_malloc(size_t size) {
|
|||
#endif
|
||||
|
||||
hallocy_small_memory_allocated += aligned_size;
|
||||
} else if (aligned_size <= hallocy_medium_allocation_size) {
|
||||
#if defined(_WIN32)
|
||||
InitOnceExecuteOnce(&HALLOCY_INIT_ONCE, hallocy_initialize_mutex, NULL, NULL);
|
||||
EnterCriticalSection(&hallocy_critical_section);
|
||||
#elif defined(__linux__)
|
||||
bool locked = false;
|
||||
while (!locked) {
|
||||
if (__sync_bool_compare_and_swap(&hallocy_futex_address, 0, 1)) {
|
||||
locked = true;
|
||||
} else {
|
||||
syscall(SYS_futex, &hallocy_futex_address, HALLOCY_FUTEX_WAIT, 1, NULL, NULL, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
HallocyMemoryHeader *previous_header = NULL;
|
||||
memory_pointer = hallocy_medium_memory_bin;
|
||||
while (memory_pointer != NULL) {
|
||||
if (memory_pointer->size >= aligned_size) {
|
||||
hallocy_medium_memory_allocated += memory_pointer->size;
|
||||
hallocy_medium_memory_freed -= memory_pointer->size;
|
||||
|
||||
if (previous_header == NULL) {
|
||||
hallocy_medium_memory_bin = hallocy_medium_memory_bin->next;
|
||||
} else {
|
||||
previous_header->next = memory_pointer->next;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
LeaveCriticalSection(&hallocy_critical_section);
|
||||
#elif defined(__linux__)
|
||||
hallocy_futex_address = 0;
|
||||
syscall(SYS_futex, &hallocy_futex_address, HALLOCY_FUTEX_WAKE, 1, NULL, NULL, 0);
|
||||
#endif
|
||||
|
||||
memory_pointer->next = NULL;
|
||||
return (void*)(memory_pointer + 1);
|
||||
}
|
||||
|
||||
previous_header = memory_pointer;
|
||||
memory_pointer = memory_pointer->next;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
if (hallocy_heap == NULL) {
|
||||
hallocy_heap = GetProcessHeap();
|
||||
}
|
||||
|
||||
memory_pointer = HeapAlloc(hallocy_heap, 0, aligned_size);
|
||||
if (memory_pointer == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hallocy_medium_allocation_size += aligned_size;
|
||||
LeaveCriticalSection(&hallocy_critical_section);
|
||||
#elif defined(__linux__)
|
||||
memory_pointer = mmap(NULL, aligned_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (memory_pointer == MAP_FAILED) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hallocy_medium_allocation_size += aligned_size;
|
||||
|
||||
hallocy_futex_address = 0;
|
||||
syscall(SYS_futex, &hallocy_futex_address, HALLOCY_FUTEX_WAKE, 1, NULL, NULL, 0);
|
||||
#endif
|
||||
} else {
|
||||
#if defined(_WIN32)
|
||||
memory_pointer = (HallocyMemoryHeader*)VirtualAlloc(NULL, aligned_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
|
|
@ -131,7 +222,7 @@ HallocyError hallocy_free(void *pointer) {
|
|||
|
||||
hallocy_small_memory_allocated -= memory_header->size;
|
||||
hallocy_small_memory_freed += memory_header->size;
|
||||
if (hallocy_small_memory_allocated == 0 && hallocy_small_memory_freed > hallocy_small_allocation_size * 10) {
|
||||
if (hallocy_small_memory_allocated == 0 && hallocy_small_memory_freed > hallocy_medium_allocation_size) {
|
||||
HallocyMemoryHeader *previous_header = NULL;
|
||||
HallocyMemoryHeader *current_header = hallocy_small_memory_bin;
|
||||
while (current_header != NULL) {
|
||||
|
|
@ -180,6 +271,82 @@ HallocyError hallocy_free(void *pointer) {
|
|||
hallocy_small_memory_allocated = 0;
|
||||
hallocy_small_memory_freed = 0;
|
||||
}
|
||||
} else if (memory_header->size <= hallocy_medium_allocation_size) {
|
||||
#if defined(_WIN32)
|
||||
InitOnceExecuteOnce(&HALLOCY_INIT_ONCE, hallocy_initialize_mutex, NULL, NULL);
|
||||
EnterCriticalSection(&hallocy_critical_section);
|
||||
#elif defined(__linux__)
|
||||
bool locked = false;
|
||||
while (!locked) {
|
||||
if (__sync_bool_compare_and_swap(&hallocy_futex_address, 0, 1)) {
|
||||
locked = true;
|
||||
} else {
|
||||
syscall(SYS_futex, &hallocy_futex_address, HALLOCY_FUTEX_WAIT, 1, NULL, NULL, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
memory_header->next = hallocy_medium_memory_bin;
|
||||
hallocy_medium_memory_bin = memory_header;
|
||||
|
||||
hallocy_medium_memory_allocated -= memory_header->size;
|
||||
hallocy_medium_memory_freed += memory_header->size;
|
||||
if (hallocy_medium_memory_allocated == 0 && hallocy_medium_memory_freed > hallocy_medium_allocation_size) {
|
||||
HallocyMemoryHeader *previous_header = NULL;
|
||||
HallocyMemoryHeader *current_header = hallocy_medium_memory_bin;
|
||||
while (current_header != NULL) {
|
||||
previous_header = current_header;
|
||||
current_header = current_header->next;
|
||||
|
||||
#if defined(_WIN32)
|
||||
bool result = HeapFree(hallocy_heap, 0, previous_header);
|
||||
if (result == false) {
|
||||
DWORD error = GetLastError();
|
||||
switch (error) {
|
||||
case ERROR_INVALID_PARAMETER:
|
||||
return HALLOCY_ERROR_INVALID_PARAM;
|
||||
|
||||
case ERROR_NOT_ENOUGH_MEMORY:
|
||||
return HALLOCY_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
case ERROR_INVALID_HANDLE:
|
||||
return HALLOCY_ERROR_INVALID_POINTER;
|
||||
|
||||
default:
|
||||
return HALLOCY_ERROR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
#elif defined(__linux__)
|
||||
int result = munmap(previous_header, previous_header->size);
|
||||
if (result == -1) {
|
||||
switch (errno) {
|
||||
case EINVAL:
|
||||
return HALLOCY_ERROR_INVALID_PARAM;
|
||||
|
||||
case ENOMEM:
|
||||
return HALLOCY_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
case EFAULT:
|
||||
return HALLOCY_ERROR_INVALID_POINTER;
|
||||
|
||||
default:
|
||||
return HALLOCY_ERROR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
hallocy_medium_memory_bin = NULL;
|
||||
hallocy_medium_memory_allocated = 0;
|
||||
hallocy_medium_memory_freed = 0;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
LeaveCriticalSection(&hallocy_critical_section);
|
||||
#elif defined(__linux__)
|
||||
hallocy_futex_address = 0;
|
||||
syscall(SYS_futex, &hallocy_futex_address, HALLOCY_FUTEX_WAKE, 1, NULL, NULL, 0);
|
||||
#endif
|
||||
} else {
|
||||
#if defined(_WIN32)
|
||||
bool result = VirtualFree(memory_header, 0, MEM_RELEASE);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#include <Hallocy/Allocator.h>
|
||||
|
||||
int main() {
|
||||
char *memory = (char *)hallocy_malloc(3);
|
||||
char *memory = (char *)hallocy_malloc(12288);
|
||||
if (memory == NULL) {
|
||||
printf("Failed it allocate memory!");
|
||||
return -1;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue