Browse Source

lightningd: speed low-level json formatting.

Make json_start_member allocate extra space, which caller can directly
print into, and also make caller call js_written_some() itself.

MCP results from 5 runs, min-max(mean +/- stddev):
	store_load_msec:35071-36817(35617.2+/-7e+02)
	vsz_kb:2637488
	store_rewrite_sec:35.790000-37.500000(36.6375+/-0.63)
	listnodes_sec:0.690000-0.780000(0.72+/-0.035)
	listchannels_sec:34.600000-36.340000(35.36+/-0.77)
	routing_sec:30.310000-30.730000(30.445+/-0.17)
	peer_write_all_sec:50.830000-52.750000(51.82+/-0.89)

MCP notable changes from previous patch (>1 stddev):
	-listnodes_sec:0.720000-0.950000(0.86+/-0.077)
	+listnodes_sec:0.690000-0.780000(0.72+/-0.035)
	-listchannels_sec:40.300000-41.080000(40.668+/-0.29)
	+listchannels_sec:34.600000-36.340000(35.36+/-0.77)

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
pr-2587
Rusty Russell 6 years ago
committed by neil saitug
parent
commit
20006b6553
  1. 56
      lightningd/json_stream.c

56
lightningd/json_stream.c

@ -94,14 +94,16 @@ static void adjust_io_write(struct io_conn *conn, ptrdiff_t delta)
conn->plan[IO_OUT].arg.u1.cp += delta; conn->plan[IO_OUT].arg.u1.cp += delta;
} }
/* Make sure js->outbuf has room for len */ /* Make sure js->outbuf has room for len: return pointer */
static void mkroom(struct json_stream *js, size_t len) static char *mkroom(struct json_stream *js, size_t len)
{ {
ptrdiff_t delta = membuf_prepare_space(&js->outbuf, len); ptrdiff_t delta = membuf_prepare_space(&js->outbuf, len);
/* If io_write is in progress, we shift it to point to new buffer pos */ /* If io_write is in progress, we shift it to point to new buffer pos */
if (js->reader) if (js->reader)
adjust_io_write(js->reader, delta); adjust_io_write(js->reader, delta);
return membuf_space(&js->outbuf);
} }
static void js_written_some(struct json_stream *js) static void js_written_some(struct json_stream *js)
@ -140,8 +142,7 @@ static void json_stream_append_vfmt(struct json_stream *js,
* membuf_num_space(&jcon->outbuf), the result was truncated! */ * membuf_num_space(&jcon->outbuf), the result was truncated! */
if (fmtlen >= membuf_num_space(&js->outbuf)) { if (fmtlen >= membuf_num_space(&js->outbuf)) {
/* Make room for NUL terminator, even though we don't want it */ /* Make room for NUL terminator, even though we don't want it */
mkroom(js, fmtlen + 1); vsprintf(mkroom(js, fmtlen + 1), fmt, ap2);
vsprintf(membuf_space(&js->outbuf), fmt, ap2);
} }
membuf_added(&js->outbuf, fmtlen); membuf_added(&js->outbuf, fmtlen);
js_written_some(js); js_written_some(js);
@ -175,16 +176,43 @@ static void check_fieldname(const struct json_stream *js,
#endif #endif
} }
static void json_start_member(struct json_stream *js, const char *fieldname) /* Caller must call js_written_some() if this returns non-NULL!
* Will never return NULL if extra is nonzero.
*/
static char *json_start_member(struct json_stream *js,
const char *fieldname, size_t extra)
{ {
char *dest;
/* Prepend comma if required. */ /* Prepend comma if required. */
if (!js->empty) if (!js->empty)
json_stream_append(js, ","); extra++;
check_fieldname(js, fieldname); check_fieldname(js, fieldname);
if (fieldname) if (fieldname)
json_stream_append_fmt(js, "\"%s\":", fieldname); extra += 1 + strlen(fieldname) + 2;
if (!extra) {
dest = NULL;
goto out;
}
dest = mkroom(js, extra);
if (!js->empty)
*(dest++) = ',';
if (fieldname) {
*(dest++) = '"';
memcpy(dest, fieldname, strlen(fieldname));
dest += strlen(fieldname);
*(dest++) = '"';
*(dest++) = ':';
}
membuf_added(&js->outbuf, extra);
out:
js->empty = false; js->empty = false;
return dest;
} }
static void js_indent(struct json_stream *js, jsmntype_t type) static void js_indent(struct json_stream *js, jsmntype_t type)
@ -208,8 +236,8 @@ static void js_unindent(struct json_stream *js, jsmntype_t type)
void json_array_start(struct json_stream *js, const char *fieldname) void json_array_start(struct json_stream *js, const char *fieldname)
{ {
json_start_member(js, fieldname); json_start_member(js, fieldname, 1)[0] = '[';
json_stream_append(js, "["); js_written_some(js);
js_indent(js, JSMN_ARRAY); js_indent(js, JSMN_ARRAY);
} }
@ -221,8 +249,8 @@ void json_array_end(struct json_stream *js)
void json_object_start(struct json_stream *js, const char *fieldname) void json_object_start(struct json_stream *js, const char *fieldname)
{ {
json_start_member(js, fieldname); json_start_member(js, fieldname, 1)[0] = '{';
json_stream_append(js, "{"); js_written_some(js);
js_indent(js, JSMN_OBJECT); js_indent(js, JSMN_OBJECT);
} }
@ -238,7 +266,7 @@ json_add_member(struct json_stream *js, const char *fieldname,
{ {
va_list ap; va_list ap;
json_start_member(js, fieldname); json_start_member(js, fieldname, 0);
va_start(ap, fmt); va_start(ap, fmt);
json_stream_append_vfmt(js, fmt, ap); json_stream_append_vfmt(js, fmt, ap);
va_end(ap); va_end(ap);
@ -251,9 +279,7 @@ void json_add_hex(struct json_stream *js, const char *fieldname,
size_t hexlen = hex_str_size(len) - 1; size_t hexlen = hex_str_size(len) - 1;
char *dest; char *dest;
json_start_member(js, fieldname); dest = json_start_member(js, fieldname, 1 + hexlen + 1);
mkroom(js, 1 + hexlen + 1);
dest = membuf_add(&js->outbuf, 1 + hexlen + 1);
dest[0] = '"'; dest[0] = '"';
if (!hex_encode(data, len, dest + 1, hexlen + 1)) if (!hex_encode(data, len, dest + 1, hexlen + 1))
abort(); abort();

Loading…
Cancel
Save