From 8238fe6acfc7db9e397ecac21e9e82cdc25c40be Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 19 Oct 2018 11:47:48 +1030 Subject: [PATCH] common/json: only maintain array of nested types if DEVELOPER mode. My test case is a mainnet gossip store with 22107 channels, and time to do `lightning-cli listchannels`: Before: `lightning-cli listchannels` DEVELOPER=0 real 0m1.396000-1.409000(1.4022+/-0.005)s After: real 0m1.307000-1.320000(1.3128+/-0.005)s Signed-off-by: Rusty Russell --- cli/Makefile | 1 + cli/lightning-cli.c | 1 + lightningd/json.c | 71 ++++++++++++++++++++++++++++----------------- 3 files changed, 47 insertions(+), 26 deletions(-) diff --git a/cli/Makefile b/cli/Makefile index 5f830d5f8..1bd4d43ab 100644 --- a/cli/Makefile +++ b/cli/Makefile @@ -4,6 +4,7 @@ LIGHTNING_CLI_OBJS := $(LIGHTNING_CLI_SRC:.c=.o) LIGHTNING_CLI_COMMON_OBJS := \ common/configdir.o \ common/json.o \ + common/memleak.o \ common/utils.o \ common/version.o diff --git a/cli/lightning-cli.c b/cli/lightning-cli.c index d4f371e8b..9a608337b 100644 --- a/cli/lightning-cli.c +++ b/cli/lightning-cli.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include diff --git a/lightningd/json.c b/lightningd/json.c index 2a44d9725..afa725c37 100644 --- a/lightningd/json.c +++ b/lightningd/json.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -480,8 +481,12 @@ bool json_tok_tok(struct command *cmd, const char *name, } struct json_result { +#if DEVELOPER /* tal_arr of types (JSMN_OBJECT/JSMN_ARRAY) we're enclosed in. */ jsmntype_t *wrapping; +#endif + /* How far to indent. */ + size_t indent; /* True if we haven't yet put an element in current wrapping */ bool empty; @@ -517,6 +522,7 @@ result_append_fmt(struct json_result *res, const char *fmt, ...) static void check_fieldname(const struct json_result *result, const char *fieldname) { +#if DEVELOPER size_t n = tal_count(result->wrapping); if (n == 0) /* Can't have a fieldname if not in anything! */ @@ -527,9 +533,22 @@ static void check_fieldname(const struct json_result *result, else /* Must have fieldnames in objects. */ assert(fieldname); +#endif } -static void result_add_indent(struct json_result *result); +static void result_append_indent(struct json_result *result) +{ + static const char indent_buf[] = " "; + size_t len; + + for (size_t i = 0; i < result->indent * 2; i += len) { + len = result->indent * 2; + if (len > sizeof(indent_buf)-1) + len = sizeof(indent_buf)-1; + /* Use tail of indent_buf string. */ + result_append(result, indent_buf + sizeof(indent_buf) - 1 - len); + } +} static void json_start_member(struct json_result *result, const char *fieldname) { @@ -539,7 +558,7 @@ static void json_start_member(struct json_result *result, const char *fieldname) else result_append(result, "\n"); - result_add_indent(result); + result_append_indent(result); check_fieldname(result, fieldname); if (fieldname) @@ -547,45 +566,39 @@ static void json_start_member(struct json_result *result, const char *fieldname) result->empty = false; } -static void result_add_indent(struct json_result *result) -{ - size_t i, indent = tal_count(result->wrapping); - - if (!indent) - return; - - for (i = 0; i < indent; i++) - result_append(result, " "); -} - -static void result_add_wrap(struct json_result *result, jsmntype_t type) +static void result_indent(struct json_result *result, jsmntype_t type) { +#if DEVELOPER *tal_arr_expand(&result->wrapping) = type; +#endif result->empty = true; + result->indent++; } -static void result_pop_wrap(struct json_result *result, jsmntype_t type) +static void result_unindent(struct json_result *result, jsmntype_t type) { - size_t indent = tal_count(result->wrapping); - - assert(indent); - assert(result->wrapping[indent-1] == type); - tal_resize(&result->wrapping, indent-1); + assert(result->indent); +#if DEVELOPER + assert(tal_count(result->wrapping) == result->indent); + assert(result->wrapping[result->indent-1] == type); + tal_resize(&result->wrapping, result->indent-1); +#endif result->empty = false; + result->indent--; } void json_array_start(struct json_result *result, const char *fieldname) { json_start_member(result, fieldname); result_append(result, "["); - result_add_wrap(result, JSMN_ARRAY); + result_indent(result, JSMN_ARRAY); } void json_array_end(struct json_result *result) { result_append(result, "\n"); - result_pop_wrap(result, JSMN_ARRAY); - result_add_indent(result); + result_unindent(result, JSMN_ARRAY); + result_append_indent(result); result_append(result, "]"); } @@ -593,14 +606,14 @@ void json_object_start(struct json_result *result, const char *fieldname) { json_start_member(result, fieldname); result_append(result, "{"); - result_add_wrap(result, JSMN_OBJECT); + result_indent(result, JSMN_OBJECT); } void json_object_end(struct json_result *result) { result_append(result, "\n"); - result_pop_wrap(result, JSMN_OBJECT); - result_add_indent(result); + result_unindent(result, JSMN_OBJECT); + result_append_indent(result); result_append(result, "}"); } @@ -695,14 +708,20 @@ struct json_result *new_json_result(const tal_t *ctx) struct json_result *r = tal(ctx, struct json_result); r->s = tal_strdup(r, ""); +#if DEVELOPER r->wrapping = tal_arr(r, jsmntype_t, 0); +#endif + r->indent = 0; r->empty = true; return r; } const char *json_result_string(const struct json_result *result) { +#if DEVELOPER assert(tal_count(result->wrapping) == 0); +#endif + assert(result->indent == 0); assert(tal_count(result->s) == strlen(result->s) + 1); return result->s; }