Skip to content

Commit c403415

Browse files
committed
lightningd: format JSON directly into json connection membuf.
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.303000-1.324000(1.3114+/-0.0091)s After: real 0m0.629000-0.695000(0.64985+/-0.019)s Signed-off-by: Rusty Russell <[email protected]>
1 parent 03e7be5 commit c403415

File tree

9 files changed

+175
-148
lines changed

9 files changed

+175
-148
lines changed

lightningd/json.c

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -491,31 +491,33 @@ struct json_result {
491491
/* True if we haven't yet put an element in current wrapping */
492492
bool empty;
493493

494-
/* tal_count() of this is strlen() + 1 */
495-
char *s;
494+
/* The command we're attached to */
495+
struct command *cmd;
496496
};
497497

498498
static void result_append(struct json_result *res, const char *str)
499499
{
500-
size_t len = tal_count(res->s) - 1;
500+
struct json_connection *jcon = res->cmd->jcon;
501501

502-
tal_resize(&res->s, len + strlen(str) + 1);
503-
strcpy(res->s + len, str);
502+
/* Don't do anything if they're disconnected. */
503+
if (!jcon)
504+
return;
505+
506+
jcon_append(jcon, str);
504507
}
505508

506509
static void PRINTF_FMT(2,3)
507510
result_append_fmt(struct json_result *res, const char *fmt, ...)
508511
{
509-
size_t len = tal_count(res->s) - 1, fmtlen;
512+
struct json_connection *jcon = res->cmd->jcon;
510513
va_list ap;
511514

512-
va_start(ap, fmt);
513-
fmtlen = vsnprintf(NULL, 0, fmt, ap);
514-
va_end(ap);
515+
/* Don't do anything if they're disconnected. */
516+
if (!jcon)
517+
return;
515518

516-
tal_resize(&res->s, len + fmtlen + 1);
517519
va_start(ap, fmt);
518-
vsprintf(res->s + len, fmt, ap);
520+
jcon_append_vfmt(jcon, fmt, ap);
519521
va_end(ap);
520522
}
521523

@@ -707,7 +709,7 @@ static struct json_result *new_json_stream(struct command *cmd)
707709
{
708710
struct json_result *r = tal(cmd, struct json_result);
709711

710-
r->s = tal_strdup(r, "");
712+
r->cmd = cmd;
711713
#if DEVELOPER
712714
r->wrapping = tal_arr(r, jsmntype_t, 0);
713715
#endif
@@ -721,27 +723,33 @@ static struct json_result *new_json_stream(struct command *cmd)
721723

722724
struct json_result *json_stream_success(struct command *cmd)
723725
{
724-
cmd->failcode = 0;
725-
return new_json_stream(cmd);
726+
struct json_result *r;
727+
r = new_json_stream(cmd);
728+
result_append(r, "\"result\" : ");
729+
return r;
726730
}
727731

728-
struct json_result *json_stream_fail(struct command *cmd,
729-
int code,
730-
const char *errmsg)
732+
struct json_result *json_stream_fail_nodata(struct command *cmd,
733+
int code,
734+
const char *errmsg)
731735
{
736+
struct json_result *r = new_json_stream(cmd);
737+
732738
assert(code);
733739
assert(errmsg);
734-
cmd->failcode = code;
735-
cmd->errmsg = tal_strdup(cmd, errmsg);
736-
return new_json_stream(cmd);
740+
741+
result_append_fmt(r, " \"error\" : "
742+
"{ \"code\" : %d,"
743+
" \"message\" : \"%s\"", code, errmsg);
744+
return r;
737745
}
738746

739-
const char *json_result_string(const struct json_result *result)
747+
struct json_result *json_stream_fail(struct command *cmd,
748+
int code,
749+
const char *errmsg)
740750
{
741-
#if DEVELOPER
742-
assert(tal_count(result->wrapping) == 0);
743-
#endif
744-
assert(result->indent == 0);
745-
assert(tal_count(result->s) == strlen(result->s) + 1);
746-
return result->s;
751+
struct json_result *r = json_stream_fail_nodata(cmd, code, errmsg);
752+
753+
result_append(r, ", \"data\" : ");
754+
return r;
747755
}

lightningd/json.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ bool json_tok_tok(struct command *cmd, const char *name,
159159
const jsmntok_t **out);
160160

161161

162-
/* Creating JSON strings */
162+
/* Creating JSON output */
163163

164164
/* '"fieldname" : [ ' or '[ ' if fieldname is NULL */
165165
void json_array_start(struct json_result *ptr, const char *fieldname);
@@ -192,6 +192,18 @@ struct json_result *json_stream_fail(struct command *cmd,
192192
int code,
193193
const char *errmsg);
194194

195+
/**
196+
* json_stream_fail_nodata - start streaming a failed json result.
197+
* @cmd: the command we're running.
198+
* @code: the error code from lightningd/jsonrpc_errors.h
199+
* @errmsg: the error string.
200+
*
201+
* This is used by command_fail(), which doesn't add any JSON data.
202+
*/
203+
struct json_result *json_stream_fail_nodata(struct command *cmd,
204+
int code,
205+
const char *errmsg);
206+
195207
/* '"fieldname" : "value"' or '"value"' if fieldname is NULL. Turns
196208
* any non-printable chars into JSON escapes, but leaves existing escapes alone.
197209
*/
@@ -227,5 +239,4 @@ void json_add_hex_talarr(struct json_result *result,
227239
const tal_t *data);
228240
void json_add_object(struct json_result *result, ...);
229241

230-
const char *json_result_string(const struct json_result *result);
231242
#endif /* LIGHTNING_LIGHTNINGD_JSON_H */

0 commit comments

Comments
 (0)