mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-12-08 03:33:32 +01:00
clusterlin: separate initial search entries per component (optimization)
Before this commit, the worst case for linearization involves clusters which break apart in several smaller components after the first candidate is included in the output linearization. Address this by never considering work items that span multiple components of what remains of the cluster.
This commit is contained in:
@@ -613,11 +613,20 @@ public:
|
||||
VecDeque<WorkItem> queue;
|
||||
queue.reserve(std::max<size_t>(256, 2 * m_todo.Count()));
|
||||
|
||||
// Create an initial entry with m_todo as undecided. Also use it as best if not provided,
|
||||
// so that during the work processing loop below, and during the add_fn/split_fn calls, we
|
||||
// do not need to deal with the best=empty case.
|
||||
if (best.feerate.IsEmpty()) best = SetInfo(m_depgraph, m_todo);
|
||||
queue.emplace_back(SetInfo<SetType>{}, SetType{m_todo});
|
||||
// Create initial entries per connected component of m_todo. While clusters themselves are
|
||||
// generally connected, this is not necessarily true after some parts have already been
|
||||
// removed from m_todo. Without this, effort can be wasted on searching "inc" sets that
|
||||
// span multiple components.
|
||||
auto to_cover = m_todo;
|
||||
do {
|
||||
auto component = m_depgraph.FindConnectedComponent(to_cover);
|
||||
to_cover -= component;
|
||||
// If best is not provided, set it to the first component, so that during the work
|
||||
// processing loop below, and during the add_fn/split_fn calls, we do not need to deal
|
||||
// with the best=empty case.
|
||||
if (best.feerate.IsEmpty()) best = SetInfo(m_depgraph, component);
|
||||
queue.emplace_back(/*inc=*/SetInfo<SetType>{}, /*und=*/std::move(component));
|
||||
} while (to_cover.Any());
|
||||
|
||||
/** Local copy of the iteration limit. */
|
||||
uint64_t iterations_left = max_iterations;
|
||||
@@ -645,7 +654,7 @@ public:
|
||||
// space runs out (see below), we know that no reallocation of the queue should ever
|
||||
// occur.
|
||||
Assume(queue.size() < queue.capacity());
|
||||
queue.emplace_back(std::move(inc), std::move(und));
|
||||
queue.emplace_back(/*inc=*/std::move(inc), /*und=*/std::move(und));
|
||||
};
|
||||
|
||||
/** Internal process function. It takes an existing work item, and splits it in two: one
|
||||
|
||||
Reference in New Issue
Block a user