mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-11-05 04:37:52 +01:00
c,cpp: optimize msgpack_zone: variable-length array of chunk -> list of chunk
This commit is contained in:
@@ -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
153
c/zone.c
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
35
c/zone.h
35
c/zone.h
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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|%>
|
||||||
|
|||||||
Reference in New Issue
Block a user