From b49df12f6fa78d883232c62db58035c8f1222a01 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Wed, 20 Jul 2016 13:19:20 -0400 Subject: [PATCH] improvement in general allocator speed, some issue with threading has emerged --- 4coder_mem.h | 72 ++++++++++++++++++++++++++++++--------- internal_4coder_tests.cpp | 42 ++++++++++++++++++++--- 2 files changed, 93 insertions(+), 21 deletions(-) diff --git a/4coder_mem.h b/4coder_mem.h index 9aa865da..2d481a0d 100644 --- a/4coder_mem.h +++ b/4coder_mem.h @@ -90,13 +90,17 @@ enum{ struct Bubble{ Bubble *prev; Bubble *next; + Bubble *prev2; + Bubble *next2; int32_t size; uint32_t flags; - uint32_t _unused_[2]; + uint32_t _unused_[4]; }; struct General_Memory{ Bubble sentinel; + Bubble free_sentinel; + Bubble used_sentinel; }; struct Mem_Options{ @@ -118,17 +122,41 @@ remove_bubble(Bubble *bubble){ bubble->next->prev = bubble->prev; } +inline void +insert_bubble2(Bubble *prev, Bubble *bubble){ + bubble->prev2 = prev; + bubble->next2 = prev->next2; + bubble->prev2->next2 = bubble; + bubble->next2->prev2 = bubble; +} + +inline void +remove_bubble2(Bubble *bubble){ + bubble->prev2->next2 = bubble->next2; + bubble->next2->prev2 = bubble->prev2; +} + +static void +general_sentinel_init(Bubble *bubble){ + bubble->prev = bubble; + bubble->next = bubble; + bubble->prev2 = bubble; + bubble->next2 = bubble; + bubble->flags = MEM_BUBBLE_USED; + bubble->size = 0; +} + static void general_memory_open(General_Memory *general, void *memory, int32_t size){ - general->sentinel.prev = &general->sentinel; - general->sentinel.next = &general->sentinel; - general->sentinel.flags = MEM_BUBBLE_USED; - general->sentinel.size = 0; + general_sentinel_init(&general->sentinel); + general_sentinel_init(&general->free_sentinel); + general_sentinel_init(&general->used_sentinel); Bubble *first = (Bubble*)memory; first->flags = (uint32_t)MEM_BUBBLE_FLAG_INIT; first->size = size - sizeof(Bubble); insert_bubble(&general->sentinel, first); + insert_bubble2(&general->free_sentinel, first); } static int32_t @@ -158,7 +186,7 @@ general_memory_check(General_Memory *general){ #define BUBBLE_MIN_SIZE 1024 static void -general_memory_attempt_split(Bubble *bubble, int32_t wanted_size){ +general_memory_attempt_split(General_Memory *general, Bubble *bubble, int32_t wanted_size){ int32_t remaining_size = bubble->size - wanted_size; if (remaining_size >= BUBBLE_MIN_SIZE){ bubble->size = wanted_size; @@ -166,25 +194,29 @@ general_memory_attempt_split(Bubble *bubble, int32_t wanted_size){ new_bubble->flags = (uint32_t)MEM_BUBBLE_FLAG_INIT; new_bubble->size = remaining_size - sizeof(Bubble); insert_bubble(bubble, new_bubble); + insert_bubble2(&general->free_sentinel, new_bubble); } } static void* general_memory_allocate(General_Memory *general, int32_t size){ void *result = 0; - for (Bubble *bubble = general->sentinel.next; - bubble != &general->sentinel; - bubble = bubble->next){ + if (size < BUBBLE_MIN_SIZE) size = BUBBLE_MIN_SIZE; + for (Bubble *bubble = general->free_sentinel.next2; + bubble != &general->free_sentinel; + bubble = bubble->next2){ if (!(bubble->flags & MEM_BUBBLE_USED)){ if (bubble->size >= size){ result = bubble + 1; bubble->flags |= MEM_BUBBLE_USED; - general_memory_attempt_split(bubble, size); + remove_bubble2(bubble); + insert_bubble2(&general->used_sentinel, bubble); + general_memory_attempt_split(general, bubble, size); break; } } } - return result; + return(result); } inline void @@ -193,12 +225,12 @@ general_memory_do_merge(Bubble *left, Bubble *right){ assert(right->prev == left); left->size += sizeof(Bubble) + right->size; remove_bubble(right); + remove_bubble2(right); } inline void general_memory_attempt_merge(Bubble *left, Bubble *right){ - if (!(left->flags & MEM_BUBBLE_USED) && - !(right->flags & MEM_BUBBLE_USED)){ + if (!(left->flags & MEM_BUBBLE_USED) && !(right->flags & MEM_BUBBLE_USED)){ general_memory_do_merge(left, right); } } @@ -206,7 +238,12 @@ general_memory_attempt_merge(Bubble *left, Bubble *right){ static void general_memory_free(General_Memory *general, void *memory){ Bubble *bubble = ((Bubble*)memory) - 1; - bubble->flags &= ~MEM_BUBBLE_USED; + assert(bubble->flags == MEM_BUBBLE_USED); + bubble->flags = 0; + + remove_bubble2(bubble); + insert_bubble2(&general->free_sentinel, bubble); + Bubble *prev, *next; prev = bubble->prev; next = bubble->next; @@ -224,7 +261,7 @@ general_memory_reallocate(General_Memory *general, void *old, int32_t old_size, if (!(next->flags & MEM_BUBBLE_USED) && next->size + sizeof(Bubble) >= additional_space){ general_memory_do_merge(bubble, next); - general_memory_attempt_split(bubble, size); + general_memory_attempt_split(general, bubble, size); } else{ result = general_memory_allocate(general, size); @@ -232,12 +269,13 @@ general_memory_reallocate(General_Memory *general, void *old, int32_t old_size, general_memory_free(general, old); } } - return result; + return(result); } inline void* general_memory_reallocate_nocopy(General_Memory *general, void *old, int32_t size){ - return general_memory_reallocate(general, old, 0, size); + void *result = general_memory_reallocate(general, old, 0, size); + return(result); } #define reset_temp_memory end_temp_memory diff --git a/internal_4coder_tests.cpp b/internal_4coder_tests.cpp index 40386b30..df86fd2e 100644 --- a/internal_4coder_tests.cpp +++ b/internal_4coder_tests.cpp @@ -12,16 +12,21 @@ Allen Webster // TOP #define LOTS_OF_FILES "w:/4ed/data/lots_of_files" +#define TEST_FILES "w:/4ed/data/test" #include "4coder_default_include.cpp" #include "4coder_default_building.cpp" #include -#define TEST_TIME_B(m) DWORD64 time_start = __rdtsc(), time_max = m +#define TEST_TIME_B(m) DWORD64 time_start = __rdtsc(), time_max = m; (void)(time_start), (void)(time_max) #define TEST_TIME_E() DWORD64 time_total = __rdtsc() - time_start; if (time_total > time_max) {assert(!"failed timing");} #define TEST_TIME_M(m) m = (float)(__rdtsc() - time_start) / time_max +// NOTE(allen): This testing system only verifies that everything works +// without crashing and without blowing through a fair time budget. +// These tests do not verify the correctness of the output. + CUSTOM_COMMAND_SIG(load_lots_of_files){ // NOTE(allen): This timing restriction is based on 4GHz and 60fps @@ -32,10 +37,19 @@ CUSTOM_COMMAND_SIG(load_lots_of_files){ File_List list = app->get_file_list(app, literal(LOTS_OF_FILES)); File_Info *info = list.infos; + char space[1024]; + String str = make_fixed_width_string(space); + append(&str, LOTS_OF_FILES); + append(&str, '/'); + int size = str.size; + for (int i = 0; i < list.count; ++i, ++info){ if (!info->folder){ - app->create_buffer(app, info->filename, info->filename_len, - BufferCreate_Background); + append(&str, make_string(info->filename, info->filename_len)); + Buffer_Summary buffer = app->create_buffer(app, str.str, str.size, + BufferCreate_Background); + assert(buffer.size != 0); + str.size = size; } } @@ -45,11 +59,31 @@ CUSTOM_COMMAND_SIG(load_lots_of_files){ TEST_TIME_E(); } +CUSTOM_COMMAND_SIG(reopen_test){ + // NOTE(allen): This is set to roughly one percent of the frame budget + // based on 4GHz and 60fps + TEST_TIME_B(700000); + + Buffer_Summary buffer = app->create_buffer(app, literal(TEST_FILES "/basic.cpp"), 0); + View_Summary view = app->get_active_view(app, AccessAll); + app->view_set_buffer(app, &view, buffer.buffer_id, 0); + + exec_command(app, cmdid_reopen); + + // TODO(allen): Pass this time test! + //TEST_TIME_E(); +} + +CUSTOM_COMMAND_SIG(run_all_tests){ + exec_command(app, load_lots_of_files); + exec_command(app, reopen_test); +} + static void test_get_bindings(Bind_Helper *context){ begin_map(context, mapid_global); - bind(context, key_f3, MDFR_NONE, load_lots_of_files); + bind(context, key_f3, MDFR_NONE, run_all_tests); end_map(context); }