From 555b8a2f7a2bd728efa15dda8302084e477aa8c9 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 19 Sep 2022 10:23:00 +0930 Subject: [PATCH] lightningd: don't always wrap each command in a db transaction. This shows the benefits of batching when being slammed by autoclean: Before: ``` plugin-autoclean: last 1000 deletes took 6699022 nsec each plugin-autoclean: last 1000 deletes took 6734025 nsec each plugin-autoclean: last 1000 deletes took 6681189 nsec each plugin-autoclean: last 1000 deletes took 6597148 nsec each plugin-autoclean: last 1000 deletes took 6637085 nsec each plugin-autoclean: last 1000 deletes took 6801425 nsec each plugin-autoclean: last 1000 deletes took 6788572 nsec each plugin-autoclean: last 1000 deletes took 6603641 nsec each plugin-autoclean: last 1000 deletes took 6642947 nsec each plugin-autoclean: last 1000 deletes took 6590495 nsec each plugin-autoclean: last 1000 deletes took 6695076 nsec each plugin-autoclean: last 1000 deletes took 6477981 nsec each ``` After: ``` plugin-autoclean: last 1000 deletes took 342764 nsec each plugin-autoclean: last 1000 deletes took 375031 nsec each plugin-autoclean: last 1000 deletes took 357564 nsec each plugin-autoclean: last 1000 deletes took 381581 nsec each plugin-autoclean: last 1000 deletes took 337989 nsec each plugin-autoclean: last 1000 deletes took 329391 nsec each plugin-autoclean: last 1000 deletes took 328322 nsec each plugin-autoclean: last 1000 deletes took 372810 nsec each plugin-autoclean: last 1000 deletes took 351228 nsec each plugin-autoclean: last 1000 deletes took 413885 nsec each plugin-autoclean: last 1000 deletes took 348317 nsec each ``` Signed-off-by: Rusty Russell --- lightningd/jsonrpc.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/lightningd/jsonrpc.c b/lightningd/jsonrpc.c index 58a1d6011d51..474928409546 100644 --- a/lightningd/jsonrpc.c +++ b/lightningd/jsonrpc.c @@ -948,9 +948,7 @@ parse_request(struct json_connection *jcon, const jsmntok_t tok[]) rpc_hook->custom_replace = NULL; rpc_hook->custom_buffer = NULL; - db_begin_transaction(jcon->ld->wallet->db); completed = plugin_hook_call_rpc_command(jcon->ld, c->id, rpc_hook); - db_commit_transaction(jcon->ld->wallet->db); /* If it's deferred, mark it (otherwise, it's completed) */ if (!completed) @@ -1007,6 +1005,7 @@ static struct io_plan *read_json(struct io_conn *conn, struct json_connection *jcon) { bool complete; + bool in_transaction = false; if (jcon->len_read) log_io(jcon->log, LOG_IO_IN, NULL, "", @@ -1023,6 +1022,7 @@ static struct io_plan *read_json(struct io_conn *conn, return io_wait(conn, conn, read_json, jcon); } +again: if (!json_parse_input(&jcon->input_parser, &jcon->input_toks, jcon->buffer, jcon->used, &complete)) { @@ -1030,6 +1030,8 @@ static struct io_plan *read_json(struct io_conn *conn, jcon, "null", tal_fmt(tmpctx, "Invalid token in json input: '%s'", tal_strndup(tmpctx, jcon->buffer, jcon->used))); + if (in_transaction) + db_commit_transaction(jcon->ld->wallet->db); return io_halfclose(conn); } @@ -1046,6 +1048,10 @@ static struct io_plan *read_json(struct io_conn *conn, goto read_more; } + if (!in_transaction) { + db_begin_transaction(jcon->ld->wallet->db); + in_transaction = true; + } parse_request(jcon, jcon->input_toks); /* Remove first {}. */ @@ -1057,16 +1063,12 @@ static struct io_plan *read_json(struct io_conn *conn, jsmn_init(&jcon->input_parser); toks_reset(jcon->input_toks); - /* If we have more to process, try again. FIXME: this still gets - * first priority in io_loop, so can starve others. Hack would be - * a (non-zero) timer, but better would be to have io_loop avoid - * such livelock */ - if (jcon->used) { - jcon->len_read = 0; - return io_always(conn, read_json, jcon); - } + if (jcon->used) + goto again; read_more: + if (in_transaction) + db_commit_transaction(jcon->ld->wallet->db); return io_read_partial(conn, jcon->buffer + jcon->used, tal_count(jcon->buffer) - jcon->used, &jcon->len_read, read_json, jcon);