From 9b6ce030d0c689fb47ab44dc32bb8e947fd9dd19 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 28 Oct 2025 11:35:58 +0200 Subject: [PATCH] sstables: remove quadratic (and possibly exponential) compile time in parse() parse() taking a list of elements is quadratic (during compile time) in that it generates recursive calls to itself, each time with one fewer parameter. The total size of the parameter lists in all these generated functions is quadratic in the initial parameter list size. It's also exponential if we ignore inlining limits, since each .then() call expands to two branches - a ready future branch and a non-ready future branch. If the compiler did not give up, we'd have 2^list_len branches. For sure the compiler does not do so indefinitely, but the effort getting there is wasted. Simplify by using a fold expression over the comma operator. Instead of passing the remaining parameter list in each step, we pass only the parameter we are processing now, making processing linear, and not generating unnecessary functions. It would be better expressed using pack expansion statements, but these are part of C++26. The largest offender is probably stats_metadata, with 21 elements. dev-mode sstables.o: text data bss dec hex filename 1760059 1312 7673 1769044 1afe54 sstables.o.before 1745533 1312 7673 1754518 1ac596 sstables.o.after We save about 15k of text with presumably a corresponding (small) decrease in compile time. Closes scylladb/scylladb#26735 --- sstables/sstables.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sstables/sstables.cc b/sstables/sstables.cc index a1d6f1b5a4..a952c25754 100644 --- a/sstables/sstables.cc +++ b/sstables/sstables.cc @@ -275,9 +275,11 @@ future<> parse(const schema&, sstable_version_types, random_access_reader& in, T // All composite parsers must come after this template future<> parse(const schema& s, sstable_version_types v, random_access_reader& in, First& first, Rest&&... rest) { - return parse(s, v, in, first).then([v, &s, &in, &rest...] { - return parse(s, v, in, std::forward(rest)...); - }); + auto fut = parse(s, v, in, first); + (..., (void)(fut = fut.then([&s, v, &in, &rest] () mutable { + return parse(s, v, in, std::forward(rest)); + }))); + return fut; } // Intended to be used for a type that describes itself through describe_type().