From 8d365458d56cc3ac9ce74d8cc1470ede30465522 Mon Sep 17 00:00:00 2001 From: frsyuki Date: Fri, 15 Jan 2010 05:27:44 +0900 Subject: [PATCH] c,cpp: optimize msgpack_zone: variable-length array of chunk -> list of chunk --- c/Makefile.am | 2 +- c/zone.c | 153 +++++++++++++++++++++-------------------------- c/zone.h | 35 +++++------ cpp/Makefile.am | 2 +- cpp/zone.hpp.erb | 5 +- 5 files changed, 88 insertions(+), 109 deletions(-) diff --git a/c/Makefile.am b/c/Makefile.am index 0a52446..23995a5 100644 --- a/c/Makefile.am +++ b/c/Makefile.am @@ -16,7 +16,7 @@ nobase_include_HEADERS = \ msgpack/zone.h # -version-info CURRENT:REVISION:AGE -libmsgpackc_la_LDFLAGS = -version-info 1:0:0 +libmsgpackc_la_LDFLAGS = -version-info 2:0:0 check_PROGRAMS = \ msgpackc_test diff --git a/c/zone.c b/c/zone.c index 79e90dc..2d8bc58 100644 --- a/c/zone.c +++ b/c/zone.c @@ -19,83 +19,61 @@ #include #include -static inline bool init_chunk_array(msgpack_zone_chunk_array* ca, size_t chunk_size) -{ - // glibcは72バイト以下のmallocが高速 - const size_t nfirst = (sizeof(msgpack_zone_chunk) < 72/2) ? - 72 / sizeof(msgpack_zone_chunk) : 8; +struct msgpack_zone_chunk { + struct msgpack_zone_chunk* next; + /* data ... */ +}; - msgpack_zone_chunk* array = (msgpack_zone_chunk*)malloc( - sizeof(msgpack_zone_chunk) * nfirst); - if(array == NULL) { +static inline bool init_chunk_list(msgpack_zone_chunk_list* cl, size_t chunk_size) +{ + msgpack_zone_chunk* chunk = (msgpack_zone_chunk*)malloc( + sizeof(msgpack_zone_chunk) + chunk_size); + if(chunk == NULL) { return false; } - const size_t sz = chunk_size; - - char* ptr = (char*)malloc(sz); - if(ptr == NULL) { - free(array); - return NULL; - } - - ca->tail = array; - ca->end = array + nfirst; - ca->array = array; - - array[0].free = sz; - array[0].ptr = ptr; - array[0].alloc = ptr; + cl->head = chunk; + cl->free = chunk_size; + cl->ptr = ((char*)chunk) + sizeof(msgpack_zone_chunk); + chunk->next = NULL; return true; } -static inline void destroy_chunk_array(msgpack_zone_chunk_array* ca) +static inline void destroy_chunk_list(msgpack_zone_chunk_list* cl) { - msgpack_zone_chunk* chunk = ca->array; - for(; chunk != ca->tail+1; ++chunk) { - free(chunk->alloc); + msgpack_zone_chunk* c = cl->head; + while(true) { + msgpack_zone_chunk* n = c->next; + free(c); + if(n != NULL) { + c = n; + } else { + break; + } } - - free(ca->array); } -static inline void clear_chunk_array(msgpack_zone_chunk_array* ca) +static inline void clear_chunk_list(msgpack_zone_chunk_list* cl, size_t chunk_size) { - msgpack_zone_chunk* chunk = ca->array + 1; - for(; chunk != ca->tail+1; ++chunk) { - free(chunk->alloc); + msgpack_zone_chunk* c = cl->head; + while(true) { + msgpack_zone_chunk* n = c->next; + if(n != NULL) { + free(c); + c = n; + } else { + break; + } } - - ca->tail = ca->array; - - ca->array[0].free += ca->array[0].ptr - (char*)ca->array[0].alloc; - ca->array[0].ptr = (char*)ca->array[0].alloc; + cl->head->next = NULL; + cl->free = chunk_size; + cl->ptr = ((char*)cl->head) + sizeof(msgpack_zone_chunk); } void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size) { - msgpack_zone_chunk_array* const ca = &zone->chunk_array; - - msgpack_zone_chunk* chunk = ++ca->tail; - - if(chunk == ca->end) { - // ca->arrayに空きがない - // ca->arrayを拡張する - - const size_t nused = ca->end - ca->array; - const size_t nnext = (ca->end - ca->array) * 2; - - chunk = (msgpack_zone_chunk*)realloc(ca->array, - sizeof(msgpack_zone_chunk) * nnext); - if(chunk == NULL) { - return NULL; - } - - ca->array = chunk; - ca->end = chunk + nnext; - chunk = ca->tail = chunk + nused; - } + msgpack_zone_chunk_list* const cl = &zone->chunk_list; size_t sz = zone->chunk_size; @@ -103,14 +81,15 @@ void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size) sz *= 2; } - char* ptr = (char*)malloc(sz); - if(ptr == NULL) { - return NULL; - } + msgpack_zone_chunk* chunk = (msgpack_zone_chunk*)malloc( + sizeof(msgpack_zone_chunk) + sz); - chunk->free = sz - size; - chunk->ptr = ptr + size; - chunk->alloc = ptr; + char* ptr = ((char*)chunk) + sizeof(msgpack_zone_chunk); + + chunk->next = cl->head; + cl->head = chunk; + cl->free = sz - size; + cl->ptr = ptr + size; return ptr; } @@ -185,19 +164,30 @@ bool msgpack_zone_push_finalizer_expand(msgpack_zone* zone, bool msgpack_zone_is_empty(msgpack_zone* zone) { - msgpack_zone_chunk_array* const ca = &zone->chunk_array; + msgpack_zone_chunk_list* const cl = &zone->chunk_list; msgpack_zone_finalizer_array* const fa = &zone->finalizer_array; - return ca->array[0].ptr == ca->array[0].alloc && - ca->tail == ca->array && + return cl->free == zone->chunk_size && cl->head->next == NULL && fa->tail == fa->array; } +void msgpack_zone_destroy(msgpack_zone* zone) +{ + destroy_finalizer_array(&zone->finalizer_array); + destroy_chunk_list(&zone->chunk_list); +} + +void msgpack_zone_clear(msgpack_zone* zone) +{ + clear_finalizer_array(&zone->finalizer_array); + clear_chunk_list(&zone->chunk_list, zone->chunk_size); +} + bool msgpack_zone_init(msgpack_zone* zone, size_t chunk_size) { zone->chunk_size = chunk_size; - if(!init_chunk_array(&zone->chunk_array, chunk_size)) { + if(!init_chunk_list(&zone->chunk_list, chunk_size)) { return false; } @@ -206,30 +196,23 @@ bool msgpack_zone_init(msgpack_zone* zone, size_t chunk_size) return true; } -void msgpack_zone_destroy(msgpack_zone* zone) -{ - destroy_finalizer_array(&zone->finalizer_array); - destroy_chunk_array(&zone->chunk_array); -} - -void msgpack_zone_clear(msgpack_zone* zone) -{ - clear_finalizer_array(&zone->finalizer_array); - clear_chunk_array(&zone->chunk_array); -} - msgpack_zone* msgpack_zone_new(size_t chunk_size) { - msgpack_zone* zone = (msgpack_zone*)malloc(sizeof(msgpack_zone)); + msgpack_zone* zone = (msgpack_zone*)malloc( + sizeof(msgpack_zone) + chunk_size); if(zone == NULL) { return NULL; } - if(!msgpack_zone_init(zone, chunk_size)) { + zone->chunk_size = chunk_size; + + if(!init_chunk_list(&zone->chunk_list, chunk_size)) { free(zone); - return NULL; + return false; } + init_finalizer_array(&zone->finalizer_array); + return zone; } diff --git a/c/zone.h b/c/zone.h index 79b51f8..e07e762 100644 --- a/c/zone.h +++ b/c/zone.h @@ -26,37 +26,34 @@ extern "C" { #endif -typedef struct msgpack_zone_chunk { - size_t free; - char* ptr; - void* alloc; -} msgpack_zone_chunk; - typedef struct msgpack_zone_finalizer { void (*func)(void* data); void* data; } msgpack_zone_finalizer; -typedef struct msgpack_zone_chunk_array { - msgpack_zone_chunk* tail; - msgpack_zone_chunk* end; - msgpack_zone_chunk* array; -} msgpack_zone_chunk_array; - typedef struct msgpack_zone_finalizer_array { msgpack_zone_finalizer* tail; msgpack_zone_finalizer* end; msgpack_zone_finalizer* array; } msgpack_zone_finalizer_array; +struct msgpack_zone_chunk; +typedef struct msgpack_zone_chunk msgpack_zone_chunk; + +typedef struct msgpack_zone_chunk_list { + size_t free; + char* ptr; + msgpack_zone_chunk* head; +} msgpack_zone_chunk_list; + typedef struct msgpack_zone { - msgpack_zone_chunk_array chunk_array; + msgpack_zone_chunk_list chunk_list; msgpack_zone_finalizer_array finalizer_array; size_t chunk_size; } msgpack_zone; #ifndef MSGPACK_ZONE_CHUNK_SIZE -#define MSGPACK_ZONE_CHUNK_SIZE 2048 +#define MSGPACK_ZONE_CHUNK_SIZE 8192 #endif bool msgpack_zone_init(msgpack_zone* zone, size_t chunk_size); @@ -85,15 +82,15 @@ void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size); void* msgpack_zone_malloc_no_align(msgpack_zone* zone, size_t size) { - msgpack_zone_chunk* chunk = zone->chunk_array.tail; + msgpack_zone_chunk_list* cl = &zone->chunk_list; - if(chunk->free < size) { + if(zone->chunk_list.free < size) { return msgpack_zone_malloc_expand(zone, size); } - char* ptr = chunk->ptr; - chunk->ptr += size; - chunk->free -= size; + char* ptr = cl->ptr; + cl->free -= size; + cl->ptr += size; return ptr; } diff --git a/cpp/Makefile.am b/cpp/Makefile.am index 0923362..99f4a32 100644 --- a/cpp/Makefile.am +++ b/cpp/Makefile.am @@ -32,7 +32,7 @@ nobase_include_HEADERS = \ libmsgpack_la_LIBADD = -L../c -lmsgpackc # -version-info CURRENT:REVISION:AGE -libmsgpack_la_LDFLAGS = -version-info 1:0:0 +libmsgpack_la_LDFLAGS = -version-info 2:0:0 check_PROGRAMS = \ msgpack_test diff --git a/cpp/zone.hpp.erb b/cpp/zone.hpp.erb index f1e4624..48988ab 100644 --- a/cpp/zone.hpp.erb +++ b/cpp/zone.hpp.erb @@ -120,9 +120,8 @@ void zone::object_destructor(void* obj) inline void zone::undo_malloc(size_t size) { - msgpack_zone_chunk* chunk = base::chunk_array.tail; - chunk->ptr -= size; - chunk->free += size; + base::chunk_list.ptr -= size; + base::chunk_list.free += size; } <%0.upto(GENERATION_LIMIT) {|i|%>