jsonparse: A bunch of performance improvements
Turrns out JSON::XS had some pretty good ideas that I could borrow.
This commit is contained in:
parent
ca8d1b72be
commit
ebe84167e7
5 changed files with 144 additions and 111 deletions
51
c/common.c
51
c/common.c
|
|
@ -2,29 +2,47 @@
|
|||
|
||||
typedef struct {
|
||||
SV *sv;
|
||||
SV *mortal;
|
||||
char *cur;
|
||||
char *end;
|
||||
size_t maxlen;
|
||||
int setutf8;
|
||||
char sbuf[4096];
|
||||
} fustr;
|
||||
|
||||
/* sv must be a new SV with a preallocated buffer */
|
||||
static void fustr_init_(pTHX_ fustr *s, SV *sv, size_t maxlen) {
|
||||
s->sv = sv;
|
||||
SvPOK_only(s->sv);
|
||||
s->cur = SvPVX(s->sv);
|
||||
s->end = SvEND(s->sv);
|
||||
static void fustr_init_(pTHX_ fustr *s, SV *mortal, size_t maxlen) {
|
||||
s->sv = NULL;
|
||||
s->cur = s->sbuf;
|
||||
s->end = s->sbuf + (maxlen > sizeof s->sbuf ? sizeof s->sbuf : maxlen);
|
||||
s->maxlen = maxlen;
|
||||
s->mortal = mortal;
|
||||
s->setutf8 = 0;
|
||||
}
|
||||
|
||||
#define fustr_start(s) (((s)->sv ? SvPVX((s)->sv) : (s)->sbuf))
|
||||
|
||||
static void fustr_grow(pTHX_ fustr *s, size_t add) {
|
||||
size_t off = s->cur - SvPVX(s->sv);
|
||||
size_t newlen = 64;
|
||||
size_t off = s->cur - (s->sv ? SvPVX(s->sv) : s->sbuf);
|
||||
size_t newlen = sizeof s->sbuf;
|
||||
char *buf;
|
||||
add += off;
|
||||
if (add > s->maxlen) croak("maximum string length exceeded");
|
||||
/* Increment to next power of two; SvGROW's default strategy is slow */
|
||||
while (newlen < add) newlen <<= 1;
|
||||
if (newlen > s->maxlen) newlen = s->maxlen;
|
||||
char *buf = SvGROW(s->sv, newlen);
|
||||
if (s->sv) {
|
||||
buf = SvGROW(s->sv, newlen);
|
||||
} else {
|
||||
if (s->mortal) {
|
||||
s->sv = s->mortal;
|
||||
sv_setpv_bufsize(s->sv, off, newlen);
|
||||
} else {
|
||||
s->sv = newSV(newlen);
|
||||
}
|
||||
SvPOK_only(s->sv);
|
||||
buf = SvPVX(s->sv);
|
||||
memcpy(buf, s->sbuf, off);
|
||||
}
|
||||
s->cur = buf + off;
|
||||
s->end = buf + (SvLEN(s->sv) > s->maxlen ? s->maxlen : SvLEN(s->sv));
|
||||
}
|
||||
|
|
@ -39,6 +57,11 @@ static inline void fustr_write_(pTHX_ fustr *s, const char *str, size_t n) {
|
|||
s->cur += n;
|
||||
}
|
||||
|
||||
static inline void fustr_write_ch_(pTHX_ fustr *s, char x) {
|
||||
fustr_reserve_(aTHX_ s, 1);
|
||||
*(s->cur++) = x;
|
||||
}
|
||||
|
||||
/* Adds n uninitialized bytes to the string and returns a buffer to write the data to */
|
||||
static inline char *fustr_write_buf_(pTHX_ fustr *s, size_t n) {
|
||||
fustr_reserve_(aTHX_ s, n);
|
||||
|
|
@ -50,13 +73,19 @@ static inline char *fustr_write_buf_(pTHX_ fustr *s, size_t n) {
|
|||
static SV *fustr_done_(pTHX_ fustr *s) {
|
||||
fustr_reserve_(aTHX_ s, 1);
|
||||
*s->cur = 0;
|
||||
SvCUR_set(s->sv, s->cur - SvPVX(s->sv));
|
||||
// TODO: SvPV_shrink_to_cur?
|
||||
if (s->sv) {
|
||||
SvCUR_set(s->sv, s->cur - SvPVX(s->sv));
|
||||
// TODO: SvPV_shrink_to_cur?
|
||||
} else {
|
||||
s->sv = newSVpvn_flags(s->sbuf, s->cur - s->sbuf, s->mortal ? SVs_TEMP : 0);
|
||||
}
|
||||
if (s->setutf8) SvUTF8_on(s->sv);
|
||||
return s->sv;
|
||||
}
|
||||
|
||||
#define fustr_init(a,b,c) fustr_init_(aTHX_ a,b,c)
|
||||
#define fustr_reserve(a,b) fustr_reserve_(aTHX_ a,b)
|
||||
#define fustr_write(a,b,c) fustr_write_(aTHX_ a,b,c)
|
||||
#define fustr_write_ch(a,b) fustr_write_ch_(aTHX_ a,b)
|
||||
#define fustr_write_buf(a,b) fustr_write_buf_(aTHX_ a,b)
|
||||
#define fustr_done(a) fustr_done_(aTHX_ a)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue