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
This commit is contained in:
committed by
Tomasz Grabiec
parent
cb30eb2e21
commit
9b6ce030d0
@@ -275,9 +275,11 @@ future<> parse(const schema&, sstable_version_types, random_access_reader& in, T
|
||||
// All composite parsers must come after this
|
||||
template<typename First, typename... Rest>
|
||||
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>(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>(rest));
|
||||
})));
|
||||
return fut;
|
||||
}
|
||||
|
||||
// Intended to be used for a type that describes itself through describe_type().
|
||||
|
||||
Reference in New Issue
Block a user