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 <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2018-10-19 11:47:48 +10:30
parent 20bed28759
commit 8238fe6acf
3 changed files with 47 additions and 26 deletions

View file

@ -4,6 +4,7 @@ LIGHTNING_CLI_OBJS := $(LIGHTNING_CLI_SRC:.c=.o)
LIGHTNING_CLI_COMMON_OBJS := \ LIGHTNING_CLI_COMMON_OBJS := \
common/configdir.o \ common/configdir.o \
common/json.o \ common/json.o \
common/memleak.o \
common/utils.o \ common/utils.o \
common/version.o common/version.o

View file

@ -8,6 +8,7 @@
#include <ccan/tal/str/str.h> #include <ccan/tal/str/str.h>
#include <common/configdir.h> #include <common/configdir.h>
#include <common/json.h> #include <common/json.h>
#include <common/memleak.h>
#include <common/utils.h> #include <common/utils.h>
#include <common/version.h> #include <common/version.h>
#include <stdio.h> #include <stdio.h>

View file

@ -4,6 +4,7 @@
#include <ccan/str/hex/hex.h> #include <ccan/str/hex/hex.h>
#include <ccan/tal/str/str.h> #include <ccan/tal/str/str.h>
#include <common/json.h> #include <common/json.h>
#include <common/memleak.h>
#include <common/type_to_string.h> #include <common/type_to_string.h>
#include <common/wireaddr.h> #include <common/wireaddr.h>
#include <gossipd/routing.h> #include <gossipd/routing.h>
@ -480,8 +481,12 @@ bool json_tok_tok(struct command *cmd, const char *name,
} }
struct json_result { struct json_result {
#if DEVELOPER
/* tal_arr of types (JSMN_OBJECT/JSMN_ARRAY) we're enclosed in. */ /* tal_arr of types (JSMN_OBJECT/JSMN_ARRAY) we're enclosed in. */
jsmntype_t *wrapping; jsmntype_t *wrapping;
#endif
/* How far to indent. */
size_t indent;
/* True if we haven't yet put an element in current wrapping */ /* True if we haven't yet put an element in current wrapping */
bool empty; 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, static void check_fieldname(const struct json_result *result,
const char *fieldname) const char *fieldname)
{ {
#if DEVELOPER
size_t n = tal_count(result->wrapping); size_t n = tal_count(result->wrapping);
if (n == 0) if (n == 0)
/* Can't have a fieldname if not in anything! */ /* Can't have a fieldname if not in anything! */
@ -527,9 +533,22 @@ static void check_fieldname(const struct json_result *result,
else else
/* Must have fieldnames in objects. */ /* Must have fieldnames in objects. */
assert(fieldname); 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) 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 else
result_append(result, "\n"); result_append(result, "\n");
result_add_indent(result); result_append_indent(result);
check_fieldname(result, fieldname); check_fieldname(result, fieldname);
if (fieldname) if (fieldname)
@ -547,45 +566,39 @@ static void json_start_member(struct json_result *result, const char *fieldname)
result->empty = false; result->empty = false;
} }
static void result_add_indent(struct json_result *result) static void result_indent(struct json_result *result, jsmntype_t type)
{
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)
{ {
#if DEVELOPER
*tal_arr_expand(&result->wrapping) = type; *tal_arr_expand(&result->wrapping) = type;
#endif
result->empty = true; 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(result->indent);
#if DEVELOPER
assert(indent); assert(tal_count(result->wrapping) == result->indent);
assert(result->wrapping[indent-1] == type); assert(result->wrapping[result->indent-1] == type);
tal_resize(&result->wrapping, indent-1); tal_resize(&result->wrapping, result->indent-1);
#endif
result->empty = false; result->empty = false;
result->indent--;
} }
void json_array_start(struct json_result *result, const char *fieldname) void json_array_start(struct json_result *result, const char *fieldname)
{ {
json_start_member(result, fieldname); json_start_member(result, fieldname);
result_append(result, "["); result_append(result, "[");
result_add_wrap(result, JSMN_ARRAY); result_indent(result, JSMN_ARRAY);
} }
void json_array_end(struct json_result *result) void json_array_end(struct json_result *result)
{ {
result_append(result, "\n"); result_append(result, "\n");
result_pop_wrap(result, JSMN_ARRAY); result_unindent(result, JSMN_ARRAY);
result_add_indent(result); result_append_indent(result);
result_append(result, "]"); result_append(result, "]");
} }
@ -593,14 +606,14 @@ void json_object_start(struct json_result *result, const char *fieldname)
{ {
json_start_member(result, fieldname); json_start_member(result, fieldname);
result_append(result, "{"); result_append(result, "{");
result_add_wrap(result, JSMN_OBJECT); result_indent(result, JSMN_OBJECT);
} }
void json_object_end(struct json_result *result) void json_object_end(struct json_result *result)
{ {
result_append(result, "\n"); result_append(result, "\n");
result_pop_wrap(result, JSMN_OBJECT); result_unindent(result, JSMN_OBJECT);
result_add_indent(result); result_append_indent(result);
result_append(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); struct json_result *r = tal(ctx, struct json_result);
r->s = tal_strdup(r, ""); r->s = tal_strdup(r, "");
#if DEVELOPER
r->wrapping = tal_arr(r, jsmntype_t, 0); r->wrapping = tal_arr(r, jsmntype_t, 0);
#endif
r->indent = 0;
r->empty = true; r->empty = true;
return r; return r;
} }
const char *json_result_string(const struct json_result *result) const char *json_result_string(const struct json_result *result)
{ {
#if DEVELOPER
assert(tal_count(result->wrapping) == 0); assert(tal_count(result->wrapping) == 0);
#endif
assert(result->indent == 0);
assert(tal_count(result->s) == strlen(result->s) + 1); assert(tal_count(result->s) == strlen(result->s) + 1);
return result->s; return result->s;
} }