From 40f17d994ccfd49c01d615816f99a312ff7c883e Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 20 Aug 2020 09:45:55 +0930 Subject: [PATCH] libplugin: don't parse partial JSON repeatedly. Tested on a test node which had made 50,000 payment, with no optimization. For comparison, time for 'listsendpays' was 0.983s. time lightning-cli -R --network=regtest --lightning-dir /tmp/ltests-k8jhvtty/test_pay_stress_1/lightning-1/ listpays > /dev/null Before: real 0m52.415s user 0m0.127s sys 0m0.044s After: real 0m42.741s user 0m0.149s sys 0m0.016s Signed-off-by: Rusty Russell Changelog-Fixed: libplugin: significant speedups for reading large JSON replies (e.g. calling listsendpays on large nodes, or listchannels / listnodes). --- plugins/libplugin.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/plugins/libplugin.c b/plugins/libplugin.c index d0cb66607..fedcec319 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -651,9 +651,11 @@ static bool rpc_read_response_one(struct plugin *plugin) bool valid; const jsmntok_t *toks, *jrtok; - /* FIXME: This could be done more efficiently by storing the - * toks and doing an incremental parse, like lightning-cli - * does. */ + /* For our convenience, lightningd always ends JSON requests with + * \n\n. We can abuse that as an optimization here.*/ + if (!memmem(plugin->rpc_buffer, plugin->rpc_used, "\n\n", 2)) + return false; + toks = json_parse_input(NULL, plugin->rpc_buffer, plugin->rpc_used, &valid); if (!toks) { @@ -681,10 +683,10 @@ static bool rpc_read_response_one(struct plugin *plugin) handle_rpc_reply(plugin, toks); - /* Move this object out of the buffer */ - memmove(plugin->rpc_buffer, plugin->rpc_buffer + toks[0].end, - tal_count(plugin->rpc_buffer) - toks[0].end); - plugin->rpc_used -= toks[0].end; + /* Move this object out of the buffer (+ 2 for \n\n)*/ + memmove(plugin->rpc_buffer, plugin->rpc_buffer + toks[0].end + 2, + tal_count(plugin->rpc_buffer) - toks[0].end - 2); + plugin->rpc_used -= toks[0].end + 2; tal_free(toks); return true;