From b893f7750cd9f9778fc6e1954662a6dc75a77702 Mon Sep 17 00:00:00 2001 From: Takatoshi Kondo Date: Fri, 23 Nov 2018 11:08:08 +0900 Subject: [PATCH] Fixed #746. Eliminated redundant zone allocation in unpacking process. ARRAY and MAP is construced on the zone. STR, BIN, and EXT refer to unpack buffer, and the buffer is reference counted via zone (finalizer). So zone is only needed if those types are appeared during unpacking process. I set zone to NULL by default. And the context has the pointer to pointer to the zone. If the context meets ARRAY, MAP, STR, BIN, or EXT, and zone (via pointer) is NULL, then allocate new zone. It is lazy zone allocation strategy. --- src/unpack.c | 80 ++++++++++++++++++++++++++++------------------------ 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/src/unpack.c b/src/unpack.c index e7e2251d..92f7c913 100644 --- a/src/unpack.c +++ b/src/unpack.c @@ -18,7 +18,7 @@ typedef struct { - msgpack_zone* z; + msgpack_zone** z; bool referenced; } unpack_user; @@ -197,7 +197,13 @@ static inline int template_callback_array(unpack_user* u, unsigned int n, msgpac // integer overflow return MSGPACK_UNPACK_NOMEM_ERROR; } - o->via.array.ptr = (msgpack_object*)msgpack_zone_malloc(u->z, size); + if (*u->z == NULL) { + *u->z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE); + if(*u->z == NULL) { + return MSGPACK_UNPACK_NOMEM_ERROR; + } + } + o->via.array.ptr = (msgpack_object*)msgpack_zone_malloc(*u->z, size); if(o->via.array.ptr == NULL) { return MSGPACK_UNPACK_NOMEM_ERROR; } return 0; } @@ -224,7 +230,13 @@ static inline int template_callback_map(unpack_user* u, unsigned int n, msgpack_ // integer overflow return MSGPACK_UNPACK_NOMEM_ERROR; } - o->via.map.ptr = (msgpack_object_kv*)msgpack_zone_malloc(u->z, size); + if (*u->z == NULL) { + *u->z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE); + if(*u->z == NULL) { + return MSGPACK_UNPACK_NOMEM_ERROR; + } + } + o->via.map.ptr = (msgpack_object_kv*)msgpack_zone_malloc(*u->z, size); if(o->via.map.ptr == NULL) { return MSGPACK_UNPACK_NOMEM_ERROR; } return 0; } @@ -245,8 +257,13 @@ static inline int template_callback_map_item(unpack_user* u, msgpack_object* c, static inline int template_callback_str(unpack_user* u, const char* b, const char* p, unsigned int l, msgpack_object* o) { - MSGPACK_UNUSED(u); MSGPACK_UNUSED(b); + if (*u->z == NULL) { + *u->z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE); + if(*u->z == NULL) { + return MSGPACK_UNPACK_NOMEM_ERROR; + } + } o->type = MSGPACK_OBJECT_STR; o->via.str.ptr = p; o->via.str.size = l; @@ -256,8 +273,13 @@ static inline int template_callback_str(unpack_user* u, const char* b, const cha static inline int template_callback_bin(unpack_user* u, const char* b, const char* p, unsigned int l, msgpack_object* o) { - MSGPACK_UNUSED(u); MSGPACK_UNUSED(b); + if (*u->z == NULL) { + *u->z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE); + if(*u->z == NULL) { + return MSGPACK_UNPACK_NOMEM_ERROR; + } + } o->type = MSGPACK_OBJECT_BIN; o->via.bin.ptr = p; o->via.bin.size = l; @@ -267,11 +289,16 @@ static inline int template_callback_bin(unpack_user* u, const char* b, const cha static inline int template_callback_ext(unpack_user* u, const char* b, const char* p, unsigned int l, msgpack_object* o) { + MSGPACK_UNUSED(b); if (l == 0) { return MSGPACK_UNPACK_PARSE_ERROR; } - MSGPACK_UNUSED(u); - MSGPACK_UNUSED(b); + if (*u->z == NULL) { + *u->z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE); + if(*u->z == NULL) { + return MSGPACK_UNPACK_NOMEM_ERROR; + } + } o->type = MSGPACK_OBJECT_EXT; o->via.ext.type = *p; o->via.ext.ptr = p + 1; @@ -317,7 +344,6 @@ bool msgpack_unpacker_init(msgpack_unpacker* mpac, size_t initial_buffer_size) { char* buffer; void* ctx; - msgpack_zone* z; if(initial_buffer_size < COUNTER_SIZE) { initial_buffer_size = COUNTER_SIZE; @@ -334,26 +360,19 @@ bool msgpack_unpacker_init(msgpack_unpacker* mpac, size_t initial_buffer_size) return false; } - z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE); - if(z == NULL) { - free(ctx); - free(buffer); - return false; - } - mpac->buffer = buffer; mpac->used = COUNTER_SIZE; mpac->free = initial_buffer_size - mpac->used; mpac->off = COUNTER_SIZE; mpac->parsed = 0; mpac->initial_buffer_size = initial_buffer_size; - mpac->z = z; + mpac->z = NULL; mpac->ctx = ctx; init_count(mpac->buffer); template_init(CTX_CAST(mpac->ctx)); - CTX_CAST(mpac->ctx)->user.z = mpac->z; + CTX_CAST(mpac->ctx)->user.z = &mpac->z; CTX_CAST(mpac->ctx)->user.referenced = false; return true; @@ -480,21 +499,15 @@ msgpack_object msgpack_unpacker_data(msgpack_unpacker* mpac) msgpack_zone* msgpack_unpacker_release_zone(msgpack_unpacker* mpac) { - msgpack_zone* r; - msgpack_zone* old; + msgpack_zone* old = mpac->z; + if (old == NULL) return NULL; if(!msgpack_unpacker_flush_zone(mpac)) { return NULL; } - r = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE); - if(r == NULL) { - return NULL; - } - - old = mpac->z; - mpac->z = r; - CTX_CAST(mpac->ctx)->user.z = mpac->z; + mpac->z = NULL; + CTX_CAST(mpac->ctx)->user.z = &mpac->z; return old; } @@ -596,7 +609,7 @@ msgpack_unpack(const char* data, size_t len, size_t* off, template_context ctx; template_init(&ctx); - ctx.user.z = result_zone; + ctx.user.z = &result_zone; ctx.user.referenced = false; e = template_execute(&ctx, data, len, &noff); @@ -633,19 +646,12 @@ msgpack_unpack_next(msgpack_unpacked* result, return MSGPACK_UNPACK_CONTINUE; } - if (!result->zone) { - result->zone = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE); - } - - if (!result->zone) { - return MSGPACK_UNPACK_NOMEM_ERROR; - } - else { + { int e; template_context ctx; template_init(&ctx); - ctx.user.z = result->zone; + ctx.user.z = &result->zone; ctx.user.referenced = false; e = template_execute(&ctx, data, len, &noff);