From e53799d779b83cbcbf9f068011178ce281ecfb21 Mon Sep 17 00:00:00 2001 From: Tokuhiro Matsuno Date: Wed, 15 Apr 2009 22:43:59 +0900 Subject: [PATCH] perl: use more efficent strategy for memory allocation.this code taken from JSON::XS. thanks to mlehmann++ --- perl/pack.c | 85 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 60 insertions(+), 25 deletions(-) diff --git a/perl/pack.c b/perl/pack.c index e9a50233..bd0c7157 100644 --- a/perl/pack.c +++ b/perl/pack.c @@ -1,3 +1,7 @@ +/* + * code is written by tokuhirom. + * buffer alocation technique is taken from JSON::XS. thanks to mlehmann. + */ #ifdef __cplusplus extern "C" { #endif @@ -17,43 +21,64 @@ extern "C" { #define msgpack_pack_inline_func_cint(name) \ static inline void msgpack_pack ## name -#define msgpack_pack_user SV* +typedef struct { + char *cur; /* SvPVX (sv) + current output position */ + char *end; /* SvEND (sv) */ + SV *sv; /* result scalar */ +} enc_t; +void need(enc_t *enc, STRLEN len); -#define msgpack_pack_append_buffer(user, buf, len) \ - sv_catpvn(user, (const char*)(buf), len); +#define msgpack_pack_user enc_t* + +#define msgpack_pack_append_buffer(enc, buf, len) \ + need(enc, len); \ + memcpy(enc->cur, buf, len); \ + enc->cur += len; #include "msgpack/pack_template.h" #define _PACK_WRAPPER(t) msgpack_pack_##t #define PACK_WRAPPER(t) _PACK_WRAPPER(t) +#define INIT_SIZE 32 /* initial scalar size to be allocated */ -static void _msgpack_pack_sv(SV* buf, SV* val) { +void need(enc_t *enc, STRLEN len) +{ + if (enc->cur + len >= enc->end) { + STRLEN cur = enc->cur - (char *)SvPVX (enc->sv); + SvGROW (enc->sv, cur + (len < (cur >> 2) ? cur >> 2 : len) + 1); + enc->cur = SvPVX (enc->sv) + cur; + enc->end = SvPVX (enc->sv) + SvLEN (enc->sv) - 1; + } +} + +static void _msgpack_pack_sv(enc_t *enc, SV* val) { if (val==NULL) { - msgpack_pack_nil(buf); + msgpack_pack_nil(enc); return; } switch (SvTYPE(val)) { case SVt_NULL: - msgpack_pack_nil(buf); + msgpack_pack_nil(enc); break; case SVt_IV: if (SvIOK_UV(val)) { - msgpack_pack_uint32(buf, SvUV(val)); + msgpack_pack_uint32(enc, SvUV(val)); } else { - PACK_WRAPPER(IVTYPE)(buf, SvIV(val)); + PACK_WRAPPER(IVTYPE)(enc, SvIV(val)); } break; case SVt_PVNV: { STRLEN len = 0; + need(enc, 1); char *pv = SvPV(val, len); if (len == 1 && *pv == '1') { - msgpack_pack_true(buf); + msgpack_pack_true(enc); } else if (len == 0 && *pv==0) { - msgpack_pack_false(buf); + msgpack_pack_false(enc); } else { - msgpack_pack_nil(buf); + msgpack_pack_nil(enc); } } break; @@ -61,25 +86,26 @@ static void _msgpack_pack_sv(SV* buf, SV* val) { { STRLEN len; char * cval = SvPV(val, len); - msgpack_pack_raw(buf, len); - msgpack_pack_raw_body(buf, cval, len); + msgpack_pack_raw(enc, len); + msgpack_pack_raw_body(enc, cval, len); } break; case SVt_NV: - PACK_WRAPPER(NVTYPE)(buf, SvNV(val)); + PACK_WRAPPER(NVTYPE)(enc, SvNV(val)); break; case SVt_PVAV: { AV* ary = (AV*)val; int len = av_len(ary) + 1; int i; - msgpack_pack_array(buf, len); + need(enc, 1); + msgpack_pack_array(enc, len); for (i=0; i