mirror of
				https://github.com/msgpack/msgpack-c.git
				synced 2025-11-04 12:17:38 +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
 | 
			
		||||
 | 
			
		||||
# -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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										153
									
								
								c/zone.c
									
									
									
									
									
								
							
							
						
						
									
										153
									
								
								c/zone.c
									
									
									
									
									
								
							@@ -19,83 +19,61 @@
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										35
									
								
								c/zone.h
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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|%>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user