From b79c1345b92d8cdb6427e0d83d7191262331fd5a Mon Sep 17 00:00:00 2001 From: tokuhirom Date: Fri, 10 Sep 2010 20:42:40 +0900 Subject: [PATCH] use gfx's standard header. --- perl/README | 43 ++++++++++++++++++++++++- perl/perlxs.h | 76 ++++++++++++++++++++++++++++++++++++++++++++ perl/xs-src/pack.c | 11 +------ perl/xs-src/unpack.c | 46 ++++++++++++--------------- 4 files changed, 140 insertions(+), 36 deletions(-) create mode 100644 perl/perlxs.h diff --git a/perl/README b/perl/README index 2ef686c2..d5fc2693 100644 --- a/perl/README +++ b/perl/README @@ -8,10 +8,29 @@ SYNOPSIS DESCRIPTION This module converts Perl data structures to MessagePack and vice versa. +ABOUT MESSAGEPACK FORMAT MessagePack is a binary-based efficient object serialization format. It enables to exchange structured objects between many languages like JSON. But unlike JSON, it is very fast and small. + ADVANTAGES + PORTABILITY + Messagepack is language independent binary serialize format. + + SMALL SIZE + say length(JSON::XS::encode_json({a=>1, b=>2})); # => 13 + say length(Storable::nfreeze({a=>1, b=>2})); # => 21 + say length(Data::MessagePack->pack({a=>1, b=>2})); # => 7 + + MessagePack format saves memory than JSON and Storable format. + + STREAMING DESERIALIZER + MessagePack supports streaming deserializer. It is useful for + networking such as RPC. + + If you want to get more informations about messagepack format, please + visit to . + METHODS my $packed = Data::MessagePack->pack($data); pack the $data to messagepack format string. @@ -23,6 +42,28 @@ Configuration Variables $Data::MessagePack::PreferInteger Pack the string as int when the value looks like int(EXPERIMENTAL). +SPEED + This is result of benchmark/serialize.pl and benchmark/deserialize.pl on + my SC440(Linux 2.6.32-23-server #37-Ubuntu SMP). + + -- serialize + JSON::XS: 2.3 + Data::MessagePack: 0.20 + Storable: 2.21 + Benchmark: timing 1000000 iterations of json, mp, storable... + json: 5 wallclock secs ( 3.95 usr + 0.00 sys = 3.95 CPU) @ 253164.56/s (n=1000000) + mp: 3 wallclock secs ( 2.69 usr + 0.00 sys = 2.69 CPU) @ 371747.21/s (n=1000000) + storable: 26 wallclock secs (27.21 usr + 0.00 sys = 27.21 CPU) @ 36751.19/s (n=1000000) + + -- deserialize + JSON::XS: 2.3 + Data::MessagePack: 0.20 + Storable: 2.21 + Benchmark: timing 1000000 iterations of json, mp, storable... + json: 4 wallclock secs ( 4.45 usr + 0.00 sys = 4.45 CPU) @ 224719.10/s (n=1000000) + mp: 6 wallclock secs ( 5.45 usr + 0.00 sys = 5.45 CPU) @ 183486.24/s (n=1000000) + storable: 7 wallclock secs ( 7.77 usr + 0.00 sys = 7.77 CPU) @ 128700.13/s (n=1000000) + AUTHORS Tokuhiro Matsuno @@ -40,5 +81,5 @@ LICENSE under the same terms as Perl itself. SEE ALSO - + is official web site for MessagePack format. diff --git a/perl/perlxs.h b/perl/perlxs.h new file mode 100644 index 00000000..441682de --- /dev/null +++ b/perl/perlxs.h @@ -0,0 +1,76 @@ +/* + perlxs.h - Standard XS header file + Copyright (c) Fuji, Goro (gfx) +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#define PERL_NO_GET_CONTEXT /* we want efficiency */ +#include + +#include +#define NO_XSLOCKS /* for exceptions */ +#include + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "ppport.h" + +/* portability stuff not supported by ppport.h yet */ + +#ifndef STATIC_INLINE /* from 5.13.4 */ +# if defined(__GNUC__) || defined(__cplusplus__) || (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) +# define STATIC_INLINE static inline +# else +# define STATIC_INLINE static +# endif +#endif /* STATIC_INLINE */ + +#ifndef __attribute__format__ +#define __attribute__format__(a,b,c) /* nothing */ +#endif + +#ifndef LIKELY /* they are just a compiler's hint */ +#define LIKELY(x) (x) +#define UNLIKELY(x) (x) +#endif + +#ifndef newSVpvs_share +#define newSVpvs_share(s) Perl_newSVpvn_share(aTHX_ STR_WITH_LEN(s), 0U) +#endif + +#ifndef get_cvs +#define get_cvs(name, flags) get_cv(name, flags) +#endif + +#ifndef GvNAME_get +#define GvNAME_get GvNAME +#endif +#ifndef GvNAMELEN_get +#define GvNAMELEN_get GvNAMELEN +#endif + +#ifndef CvGV_set +#define CvGV_set(cv, gv) (CvGV(cv) = (gv)) +#endif + +/* general utility */ + +#if PERL_BCDVERSION >= 0x5008005 +#define LooksLikeNumber(x) looks_like_number(x) +#else +#define LooksLikeNumber(x) (SvPOKp(x) ? looks_like_number(x) : (I32)SvNIOKp(x)) +#endif + +#define newAV_mortal() (AV*)sv_2mortal((SV*)newAV()) +#define newHV_mortal() (HV*)sv_2mortal((SV*)newHV()) + +#define DECL_BOOT(name) EXTERN_C XS(CAT2(boot_, name)) +#define CALL_BOOT(name) STMT_START { \ + PUSHMARK(SP); \ + CALL_FPTR(CAT2(boot_, name))(aTHX_ cv); \ + } STMT_END diff --git a/perl/xs-src/pack.c b/perl/xs-src/pack.c index 93b2e2f4..62eb0024 100644 --- a/perl/xs-src/pack.c +++ b/perl/xs-src/pack.c @@ -2,16 +2,7 @@ * code is written by tokuhirom. * buffer alocation technique is taken from JSON::XS. thanks to mlehmann. */ -#ifdef __cplusplus -extern "C" { -#endif -#include "EXTERN.h" -#include "perl.h" -#include "XSUB.h" -#include "ppport.h" -#ifdef __cplusplus -}; -#endif +#include "perlxs.h" #include "msgpack/pack_define.h" diff --git a/perl/xs-src/unpack.c b/perl/xs-src/unpack.c index eb6e0ddb..20a07372 100644 --- a/perl/xs-src/unpack.c +++ b/perl/xs-src/unpack.c @@ -2,13 +2,9 @@ extern "C" { #endif -#include "EXTERN.h" -#include "perl.h" -#include "XSUB.h" -#include "util.h" #define NEED_newRV_noinc #define NEED_sv_2pv_flags -#include "ppport.h" +#include "perlxs.h" #ifdef __cplusplus }; @@ -38,7 +34,7 @@ typedef struct { /* ---------------------------------------------------------------------- */ /* utility functions */ -static INLINE SV * +STATIC_INLINE SV * get_bool (const char *name) { SV * sv = sv_mortalcopy(get_sv( name, 1 )); @@ -60,19 +56,19 @@ static SV* template_data(msgpack_unpack_t* u); static int template_execute(msgpack_unpack_t* u, const char* data, size_t len, size_t* off); -static INLINE SV* template_callback_root(unpack_user* u) +STATIC_INLINE SV* template_callback_root(unpack_user* u) { return &PL_sv_undef; } -static INLINE int template_callback_uint8(unpack_user* u, uint8_t d, SV** o) +STATIC_INLINE int template_callback_uint8(unpack_user* u, uint8_t d, SV** o) { *o = sv_2mortal(newSVuv(d)); return 0; } -static INLINE int template_callback_uint16(unpack_user* u, uint16_t d, SV** o) +STATIC_INLINE int template_callback_uint16(unpack_user* u, uint16_t d, SV** o) { *o = sv_2mortal(newSVuv(d)); return 0; } -static INLINE int template_callback_uint32(unpack_user* u, uint32_t d, SV** o) +STATIC_INLINE int template_callback_uint32(unpack_user* u, uint32_t d, SV** o) { *o = sv_2mortal(newSVuv(d)); return 0; } -static INLINE int template_callback_uint64(unpack_user* u, uint64_t d, SV** o) +STATIC_INLINE int template_callback_uint64(unpack_user* u, uint64_t d, SV** o) { #if IVSIZE==4 *o = sv_2mortal(newSVnv(d)); @@ -82,47 +78,47 @@ static INLINE int template_callback_uint64(unpack_user* u, uint64_t d, SV** o) return 0; } -static INLINE int template_callback_int8(unpack_user* u, int8_t d, SV** o) +STATIC_INLINE int template_callback_int8(unpack_user* u, int8_t d, SV** o) { *o = sv_2mortal(newSViv((long)d)); return 0; } -static INLINE int template_callback_int16(unpack_user* u, int16_t d, SV** o) +STATIC_INLINE int template_callback_int16(unpack_user* u, int16_t d, SV** o) { *o = sv_2mortal(newSViv((long)d)); return 0; } -static INLINE int template_callback_int32(unpack_user* u, int32_t d, SV** o) +STATIC_INLINE int template_callback_int32(unpack_user* u, int32_t d, SV** o) { *o = sv_2mortal(newSViv((long)d)); return 0; } -static INLINE int template_callback_int64(unpack_user* u, int64_t d, SV** o) +STATIC_INLINE int template_callback_int64(unpack_user* u, int64_t d, SV** o) { *o = sv_2mortal(newSViv(d)); return 0; } -static INLINE int template_callback_float(unpack_user* u, float d, SV** o) +STATIC_INLINE int template_callback_float(unpack_user* u, float d, SV** o) { *o = sv_2mortal(newSVnv(d)); return 0; } -static INLINE int template_callback_double(unpack_user* u, double d, SV** o) +STATIC_INLINE int template_callback_double(unpack_user* u, double d, SV** o) { *o = sv_2mortal(newSVnv(d)); return 0; } /* &PL_sv_undef is not so good. see http://gist.github.com/387743 */ -static INLINE int template_callback_nil(unpack_user* u, SV** o) +STATIC_INLINE int template_callback_nil(unpack_user* u, SV** o) { *o = sv_newmortal(); return 0; } -static INLINE int template_callback_true(unpack_user* u, SV** o) +STATIC_INLINE int template_callback_true(unpack_user* u, SV** o) { *o = get_bool("Data::MessagePack::true") ; return 0; } -static INLINE int template_callback_false(unpack_user* u, SV** o) +STATIC_INLINE int template_callback_false(unpack_user* u, SV** o) { *o = get_bool("Data::MessagePack::false") ; return 0; } -static INLINE int template_callback_array(unpack_user* u, unsigned int n, SV** o) +STATIC_INLINE int template_callback_array(unpack_user* u, unsigned int n, SV** o) { AV* a = (AV*)sv_2mortal((SV*)newAV()); *o = sv_2mortal((SV*)newRV_inc((SV*)a)); av_extend(a, n); return 0; } -static INLINE int template_callback_array_item(unpack_user* u, SV** c, SV* o) +STATIC_INLINE int template_callback_array_item(unpack_user* u, SV** c, SV* o) { av_push((AV*)SvRV(*c), o); SvREFCNT_inc(o); return 0; } /* FIXME set value directry RARRAY_PTR(obj)[RARRAY_LEN(obj)++] */ -static INLINE int template_callback_map(unpack_user* u, unsigned int n, SV** o) +STATIC_INLINE int template_callback_map(unpack_user* u, unsigned int n, SV** o) { HV * h = (HV*)sv_2mortal((SV*)newHV()); *o = sv_2mortal(newRV_inc((SV*)h)); return 0; } -static INLINE int template_callback_map_item(unpack_user* u, SV** c, SV* k, SV* v) +STATIC_INLINE int template_callback_map_item(unpack_user* u, SV** c, SV* k, SV* v) { hv_store_ent((HV*)SvRV(*c), k, v, 0); SvREFCNT_inc(v); return 0; } -static INLINE int template_callback_raw(unpack_user* u, const char* b, const char* p, unsigned int l, SV** o) +STATIC_INLINE int template_callback_raw(unpack_user* u, const char* b, const char* p, unsigned int l, SV** o) { *o = sv_2mortal((l==0) ? newSVpv("", 0) : newSVpv(p, l)); return 0; } /* { *o = newSVpvn_flags(p, l, SVs_TEMP); return 0; } <= this does not works. */