diff options
author | Mark Pulford <mark@kyne.com.au> | 2011-05-03 22:47:09 +0930 |
---|---|---|
committer | Mark Pulford <mark@kyne.com.au> | 2011-05-03 22:47:09 +0930 |
commit | e1001b2f316448ce171434f31410ffc150877a82 (patch) | |
tree | 69622033d622d5ee7bafc5aaa888da345e5143a8 | |
parent | 4cfafe0883da22cc020bb4e92d652ce16500b104 (diff) | |
download | lua-cjson-e1001b2f316448ce171434f31410ffc150877a82.tar.gz lua-cjson-e1001b2f316448ce171434f31410ffc150877a82.tar.bz2 lua-cjson-e1001b2f316448ce171434f31410ffc150877a82.zip |
Preallocate temporary decode string buffer
The preallocated buffer removes the need for buffer length checks while
processing strings and results in a 10 - 15% speedup.
-rw-r--r-- | lua_cjson.c | 25 | ||||
-rw-r--r-- | strbuf.h | 6 |
2 files changed, 20 insertions, 11 deletions
diff --git a/lua_cjson.c b/lua_cjson.c index 39e22ad..5f518f6 100644 --- a/lua_cjson.c +++ b/lua_cjson.c | |||
@@ -25,15 +25,13 @@ | |||
25 | /* Caveats: | 25 | /* Caveats: |
26 | * - JSON "null" values are represented as lightuserdata since Lua | 26 | * - JSON "null" values are represented as lightuserdata since Lua |
27 | * tables cannot contain "nil". Compare with cjson.null. | 27 | * tables cannot contain "nil". Compare with cjson.null. |
28 | * - Only standard JSON escapes and \u0000 are used when encoding | ||
29 | * JSON. Most unprintable characters are not escaped. | ||
30 | * - Invalid UTF-8 characters are not detected and will be passed | 28 | * - Invalid UTF-8 characters are not detected and will be passed |
31 | * untouched. | 29 | * untouched. |
32 | * - Javascript comments are not part of the JSON spec, and are not | 30 | * - Javascript comments are not part of the JSON spec, and are not |
33 | * supported. | 31 | * supported. |
34 | * | 32 | * |
35 | * Note: Decoding is slower than encoding. Lua probably spends | 33 | * Note: Decoding is slower than encoding. Lua spends significant |
36 | * significant time rehashing tables when parsing JSON since it is | 34 | * time (30%) managing tables when parsing JSON since it is |
37 | * difficult to know object/array sizes ahead of time. | 35 | * difficult to know object/array sizes ahead of time. |
38 | */ | 36 | */ |
39 | 37 | ||
@@ -655,8 +653,8 @@ static int json_append_unicode_escape(json_parse_t *json) | |||
655 | return -1; | 653 | return -1; |
656 | } | 654 | } |
657 | 655 | ||
658 | /* Append bytes and advance counter */ | 656 | /* Append bytes and advance index */ |
659 | strbuf_append_mem(json->tmp, utf8, len); | 657 | strbuf_append_mem_unsafe(json->tmp, utf8, len); |
660 | json->index += 6; | 658 | json->index += 6; |
661 | 659 | ||
662 | return 0; | 660 | return 0; |
@@ -716,7 +714,7 @@ static void json_next_string_token(json_parse_t *json, json_token_t *token) | |||
716 | } | 714 | } |
717 | /* Append normal character or translated single character | 715 | /* Append normal character or translated single character |
718 | * Unicode escapes are handled above */ | 716 | * Unicode escapes are handled above */ |
719 | strbuf_append_char(json->tmp, ch); | 717 | strbuf_append_char_unsafe(json->tmp, ch); |
720 | json->index++; | 718 | json->index++; |
721 | } | 719 | } |
722 | json->index++; /* Eat final quote (") */ | 720 | json->index++; /* Eat final quote (") */ |
@@ -1000,7 +998,7 @@ static void json_process_value(lua_State *l, json_parse_t *json, json_token_t *t | |||
1000 | } | 998 | } |
1001 | 999 | ||
1002 | /* json_text must be null terminated string */ | 1000 | /* json_text must be null terminated string */ |
1003 | static void lua_json_decode(lua_State *l, const char *json_text) | 1001 | static void lua_json_decode(lua_State *l, const char *json_text, int json_len) |
1004 | { | 1002 | { |
1005 | json_parse_t json; | 1003 | json_parse_t json; |
1006 | json_token_t token; | 1004 | json_token_t token; |
@@ -1008,7 +1006,11 @@ static void lua_json_decode(lua_State *l, const char *json_text) | |||
1008 | json.cfg = json_fetch_config(l); | 1006 | json.cfg = json_fetch_config(l); |
1009 | json.data = json_text; | 1007 | json.data = json_text; |
1010 | json.index = 0; | 1008 | json.index = 0; |
1011 | json.tmp = strbuf_new(0); | 1009 | |
1010 | /* Ensure the temporary buffer can hold the entire string. | ||
1011 | * This means we no longer need to do length checks since the decoded | ||
1012 | * string must be smaller than the entire json string */ | ||
1013 | json.tmp = strbuf_new(json_len); | ||
1012 | 1014 | ||
1013 | json_next_token(&json, &token); | 1015 | json_next_token(&json, &token); |
1014 | json_process_value(l, &json, &token); | 1016 | json_process_value(l, &json, &token); |
@@ -1025,11 +1027,12 @@ static void lua_json_decode(lua_State *l, const char *json_text) | |||
1025 | static int json_decode(lua_State *l) | 1027 | static int json_decode(lua_State *l) |
1026 | { | 1028 | { |
1027 | const char *json; | 1029 | const char *json; |
1030 | size_t len; | ||
1028 | 1031 | ||
1029 | luaL_argcheck(l, lua_gettop(l) <= 1, 2, "found too many arguments"); | 1032 | luaL_argcheck(l, lua_gettop(l) <= 1, 2, "found too many arguments"); |
1030 | json = luaL_checkstring(l, 1); | 1033 | json = luaL_checklstring(l, 1, &len); |
1031 | 1034 | ||
1032 | lua_json_decode(l, json); | 1035 | lua_json_decode(l, json, len); |
1033 | 1036 | ||
1034 | return 1; | 1037 | return 1; |
1035 | } | 1038 | } |
@@ -114,6 +114,12 @@ static inline void strbuf_append_mem(strbuf_t *s, const char *c, int len) | |||
114 | s->length += len; | 114 | s->length += len; |
115 | } | 115 | } |
116 | 116 | ||
117 | static inline void strbuf_append_mem_unsafe(strbuf_t *s, const char *c, int len) | ||
118 | { | ||
119 | memcpy(s->buf + s->length, c, len); | ||
120 | s->length += len; | ||
121 | } | ||
122 | |||
117 | static inline void strbuf_ensure_null(strbuf_t *s) | 123 | static inline void strbuf_ensure_null(strbuf_t *s) |
118 | { | 124 | { |
119 | s->buf[s->length] = 0; | 125 | s->buf[s->length] = 0; |