From b4f17508b155f5b1077016d859e073e875772180 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 20 Nov 2025 12:07:16 +1030 Subject: [PATCH] libplugin: add spamlistcommand This hammers lightingd with `listinvoices` commands. $ VALGRIND=0 TEST_DB_PROVIDER=postgres eatmydata uv run pytest -v tests/benchmark.py::test_spam_listcommands sqlite3: test_spam_listcommands 2.1193 2.4524 2.2343 0.1341 2.2229 0.1709 1;0 0.4476 5 1 PostgreSQL: test_spam_listcommands 6.5572 6.8440 6.7067 0.1032 6.6967 0.1063 2;0 0.1491 5 1 Signed-off-by: Rusty Russell --- tests/benchmark.py | 9 +++++++++ tests/plugins/test_libplugin.c | 24 ++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/tests/benchmark.py b/tests/benchmark.py index 81ab387d5..ec0062e82 100644 --- a/tests/benchmark.py +++ b/tests/benchmark.py @@ -218,4 +218,13 @@ def test_spam_commands(node_factory, bitcoind, benchmark): plugin = os.path.join(os.getcwd(), "tests/plugins/test_libplugin") l1 = get_bench_node(node_factory, extra_options={"plugin": plugin}) + # This calls "batch" 1M times (which doesn't need a transaction) benchmark(l1.rpc.spamcommand, 1_000_000) + + +def test_spam_listcommands(node_factory, bitcoind, benchmark): + plugin = os.path.join(os.getcwd(), "tests/plugins/test_libplugin") + l1 = get_bench_node(node_factory, extra_options={"plugin": plugin}) + + # This calls "listinvoice" 100,000 times (which doesn't need a transaction commit) + benchmark(l1.rpc.spamlistcommand, 100_000) diff --git a/tests/plugins/test_libplugin.c b/tests/plugins/test_libplugin.c index 2abf1f7f4..c51ab55be 100644 --- a/tests/plugins/test_libplugin.c +++ b/tests/plugins/test_libplugin.c @@ -234,6 +234,26 @@ static struct command_result *json_spamcommand(struct command *cmd, return batch_done(cmd, batch); } +static struct command_result *json_spamlistcommand(struct command *cmd, + const char *buf, + const jsmntok_t *params) +{ + u64 *iterations; + struct request_batch *batch; + + if (!param(cmd, buf, params, + p_req("iterations", param_u64, &iterations), + NULL)) + return command_param_failed(); + + batch = request_batch_new(cmd, NULL, spam_errcb, spam_done, NULL); + for (size_t i = 0; i < *iterations; i++) { + struct out_req *req = add_to_batch(cmd, batch, "listinvoices"); + send_outreq(req); + } + return batch_done(cmd, batch); +} + static char *set_dynamic(struct plugin *plugin, const char *arg, @@ -312,6 +332,10 @@ static const struct plugin_command commands[] = { { "spamcommand", json_spamcommand, }, + { + "spamlistcommand", + json_spamlistcommand, + }, }; static const char *before[] = { "dummy", NULL };