c,cpp: optimize msgpack_zone: variable-length array of chunk -> list of chunk

This commit is contained in:
frsyuki
2010-01-15 05:27:44 +09:00
parent 55cfbf378e
commit 8d365458d5
5 changed files with 88 additions and 109 deletions

View File

@@ -16,7 +16,7 @@ nobase_include_HEADERS = \
msgpack/zone.h msgpack/zone.h
# -version-info CURRENT:REVISION:AGE # -version-info CURRENT:REVISION:AGE
libmsgpackc_la_LDFLAGS = -version-info 1:0:0 libmsgpackc_la_LDFLAGS = -version-info 2:0:0
check_PROGRAMS = \ check_PROGRAMS = \
msgpackc_test msgpackc_test

153
c/zone.c
View File

@@ -19,83 +19,61 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
static inline bool init_chunk_array(msgpack_zone_chunk_array* ca, size_t chunk_size) struct msgpack_zone_chunk {
{ struct msgpack_zone_chunk* next;
// glibcは72バイト以下のmallocが高速 /* data ... */
const size_t nfirst = (sizeof(msgpack_zone_chunk) < 72/2) ? };
72 / sizeof(msgpack_zone_chunk) : 8;
msgpack_zone_chunk* array = (msgpack_zone_chunk*)malloc( static inline bool init_chunk_list(msgpack_zone_chunk_list* cl, size_t chunk_size)
sizeof(msgpack_zone_chunk) * nfirst); {
if(array == NULL) { msgpack_zone_chunk* chunk = (msgpack_zone_chunk*)malloc(
sizeof(msgpack_zone_chunk) + chunk_size);
if(chunk == NULL) {
return false; return false;
} }
const size_t sz = chunk_size; cl->head = chunk;
cl->free = chunk_size;
char* ptr = (char*)malloc(sz); cl->ptr = ((char*)chunk) + sizeof(msgpack_zone_chunk);
if(ptr == NULL) { chunk->next = 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;
return true; 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; msgpack_zone_chunk* c = cl->head;
for(; chunk != ca->tail+1; ++chunk) { while(true) {
free(chunk->alloc); 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; msgpack_zone_chunk* c = cl->head;
for(; chunk != ca->tail+1; ++chunk) { while(true) {
free(chunk->alloc); msgpack_zone_chunk* n = c->next;
if(n != NULL) {
free(c);
c = n;
} else {
break;
} }
}
ca->tail = ca->array; cl->head->next = NULL;
cl->free = chunk_size;
ca->array[0].free += ca->array[0].ptr - (char*)ca->array[0].alloc; cl->ptr = ((char*)cl->head) + sizeof(msgpack_zone_chunk);
ca->array[0].ptr = (char*)ca->array[0].alloc;
} }
void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size) void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size)
{ {
msgpack_zone_chunk_array* const ca = &zone->chunk_array; msgpack_zone_chunk_list* const cl = &zone->chunk_list;
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;
}
size_t sz = zone->chunk_size; size_t sz = zone->chunk_size;
@@ -103,14 +81,15 @@ void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size)
sz *= 2; sz *= 2;
} }
char* ptr = (char*)malloc(sz); msgpack_zone_chunk* chunk = (msgpack_zone_chunk*)malloc(
if(ptr == NULL) { sizeof(msgpack_zone_chunk) + sz);
return NULL;
}
chunk->free = sz - size; char* ptr = ((char*)chunk) + sizeof(msgpack_zone_chunk);
chunk->ptr = ptr + size;
chunk->alloc = ptr; chunk->next = cl->head;
cl->head = chunk;
cl->free = sz - size;
cl->ptr = ptr + size;
return ptr; return ptr;
} }
@@ -185,19 +164,30 @@ bool msgpack_zone_push_finalizer_expand(msgpack_zone* zone,
bool msgpack_zone_is_empty(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; msgpack_zone_finalizer_array* const fa = &zone->finalizer_array;
return ca->array[0].ptr == ca->array[0].alloc && return cl->free == zone->chunk_size && cl->head->next == NULL &&
ca->tail == ca->array &&
fa->tail == fa->array; 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) bool msgpack_zone_init(msgpack_zone* zone, size_t chunk_size)
{ {
zone->chunk_size = 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; return false;
} }
@@ -206,30 +196,23 @@ bool msgpack_zone_init(msgpack_zone* zone, size_t chunk_size)
return true; 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* 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) { if(zone == NULL) {
return 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); free(zone);
return NULL; return false;
} }
init_finalizer_array(&zone->finalizer_array);
return zone; return zone;
} }

View File

@@ -26,37 +26,34 @@ extern "C" {
#endif #endif
typedef struct msgpack_zone_chunk {
size_t free;
char* ptr;
void* alloc;
} msgpack_zone_chunk;
typedef struct msgpack_zone_finalizer { typedef struct msgpack_zone_finalizer {
void (*func)(void* data); void (*func)(void* data);
void* data; void* data;
} msgpack_zone_finalizer; } 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 { typedef struct msgpack_zone_finalizer_array {
msgpack_zone_finalizer* tail; msgpack_zone_finalizer* tail;
msgpack_zone_finalizer* end; msgpack_zone_finalizer* end;
msgpack_zone_finalizer* array; msgpack_zone_finalizer* array;
} 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 { typedef struct msgpack_zone {
msgpack_zone_chunk_array chunk_array; msgpack_zone_chunk_list chunk_list;
msgpack_zone_finalizer_array finalizer_array; msgpack_zone_finalizer_array finalizer_array;
size_t chunk_size; size_t chunk_size;
} msgpack_zone; } msgpack_zone;
#ifndef MSGPACK_ZONE_CHUNK_SIZE #ifndef MSGPACK_ZONE_CHUNK_SIZE
#define MSGPACK_ZONE_CHUNK_SIZE 2048 #define MSGPACK_ZONE_CHUNK_SIZE 8192
#endif #endif
bool msgpack_zone_init(msgpack_zone* zone, size_t chunk_size); 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) 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); return msgpack_zone_malloc_expand(zone, size);
} }
char* ptr = chunk->ptr; char* ptr = cl->ptr;
chunk->ptr += size; cl->free -= size;
chunk->free -= size; cl->ptr += size;
return ptr; return ptr;
} }

View File

@@ -32,7 +32,7 @@ nobase_include_HEADERS = \
libmsgpack_la_LIBADD = -L../c -lmsgpackc libmsgpack_la_LIBADD = -L../c -lmsgpackc
# -version-info CURRENT:REVISION:AGE # -version-info CURRENT:REVISION:AGE
libmsgpack_la_LDFLAGS = -version-info 1:0:0 libmsgpack_la_LDFLAGS = -version-info 2:0:0
check_PROGRAMS = \ check_PROGRAMS = \
msgpack_test msgpack_test

View File

@@ -120,9 +120,8 @@ void zone::object_destructor(void* obj)
inline void zone::undo_malloc(size_t size) inline void zone::undo_malloc(size_t size)
{ {
msgpack_zone_chunk* chunk = base::chunk_array.tail; base::chunk_list.ptr -= size;
chunk->ptr -= size; base::chunk_list.free += size;
chunk->free += size;
} }
<%0.upto(GENERATION_LIMIT) {|i|%> <%0.upto(GENERATION_LIMIT) {|i|%>