Skip to content

Commit 9e43e4c

Browse files
committed
clusterlin: use feerate-sorted depgraph in SearchCandidateFinder
This is a requirement for a future commit, which will rely on quickly iterating over transaction sets in decreasing individual feerate order.
1 parent b80e6df commit 9e43e4c

File tree

1 file changed

+59
-16
lines changed

1 file changed

+59
-16
lines changed

src/cluster_linearize.h

Lines changed: 59 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -563,23 +563,60 @@ class SearchCandidateFinder
563563
{
564564
/** Internal RNG. */
565565
InsecureRandomContext m_rng;
566-
/** Internal dependency graph for the cluster. */
567-
const DepGraph<SetType>& m_depgraph;
568-
/** Which transactions are left to do (sorted indices). */
566+
/** m_sorted_to_original[i] is the original position that sorted transaction position i had. */
567+
std::vector<ClusterIndex> m_sorted_to_original;
568+
/** m_original_to_sorted[i] is the sorted position original transaction position i has. */
569+
std::vector<ClusterIndex> m_original_to_sorted;
570+
/** Internal dependency graph for the cluster (with transactions in decreasing individual
571+
* feerate order). */
572+
DepGraph<SetType> m_sorted_depgraph;
573+
/** Which transactions are left to do (indices in m_sorted_depgraph's order). */
569574
SetType m_todo;
570575

576+
/** Given a set of transactions with sorted indices, get their original indices. */
577+
SetType SortedToOriginal(const SetType& arg) const noexcept
578+
{
579+
SetType ret;
580+
for (auto pos : arg) ret.Set(m_sorted_to_original[pos]);
581+
return ret;
582+
}
583+
584+
/** Given a set of transactions with original indices, get their sorted indices. */
585+
SetType OriginalToSorted(const SetType& arg) const noexcept
586+
{
587+
SetType ret;
588+
for (auto pos : arg) ret.Set(m_original_to_sorted[pos]);
589+
return ret;
590+
}
591+
571592
public:
572593
/** Construct a candidate finder for a graph.
573594
*
574595
* @param[in] depgraph Dependency graph for the to-be-linearized cluster.
575596
* @param[in] rng_seed A random seed to control the search order.
576597
*
577-
* Complexity: O(1).
598+
* Complexity: O(N^2) where N=depgraph.Count().
578599
*/
579-
SearchCandidateFinder(const DepGraph<SetType>& depgraph LIFETIMEBOUND, uint64_t rng_seed) noexcept :
600+
SearchCandidateFinder(const DepGraph<SetType>& depgraph, uint64_t rng_seed) noexcept :
580601
m_rng(rng_seed),
581-
m_depgraph(depgraph),
582-
m_todo(SetType::Fill(depgraph.TxCount())) {}
602+
m_sorted_to_original(depgraph.TxCount()),
603+
m_original_to_sorted(depgraph.TxCount()),
604+
m_todo(SetType::Fill(depgraph.TxCount()))
605+
{
606+
// Determine reordering mapping, by sorting by decreasing feerate.
607+
std::iota(m_sorted_to_original.begin(), m_sorted_to_original.end(), ClusterIndex{0});
608+
std::sort(m_sorted_to_original.begin(), m_sorted_to_original.end(), [&](auto a, auto b) {
609+
auto feerate_cmp = depgraph.FeeRate(a) <=> depgraph.FeeRate(b);
610+
if (feerate_cmp == 0) return a < b;
611+
return feerate_cmp > 0;
612+
});
613+
// Compute reverse mapping.
614+
for (ClusterIndex i = 0; i < depgraph.TxCount(); ++i) {
615+
m_original_to_sorted[m_sorted_to_original[i]] = i;
616+
}
617+
// Compute reordered dependency graph.
618+
m_sorted_depgraph = DepGraph(depgraph, m_original_to_sorted);
619+
}
583620

584621
/** Check whether any unlinearized transactions remain. */
585622
bool AllDone() const noexcept
@@ -608,6 +645,9 @@ class SearchCandidateFinder
608645
{
609646
Assume(!AllDone());
610647

648+
// Convert the provided best to internal sorted indices.
649+
best.transactions = OriginalToSorted(best.transactions);
650+
611651
/** Type for work queue items. */
612652
struct WorkItem
613653
{
@@ -641,12 +681,12 @@ class SearchCandidateFinder
641681
// span multiple components.
642682
auto to_cover = m_todo;
643683
do {
644-
auto component = m_depgraph.FindConnectedComponent(to_cover);
684+
auto component = m_sorted_depgraph.FindConnectedComponent(to_cover);
645685
to_cover -= component;
646686
// If best is not provided, set it to the first component, so that during the work
647687
// processing loop below, and during the add_fn/split_fn calls, we do not need to deal
648688
// with the best=empty case.
649-
if (best.feerate.IsEmpty()) best = SetInfo(m_depgraph, component);
689+
if (best.feerate.IsEmpty()) best = SetInfo(m_sorted_depgraph, component);
650690
queue.emplace_back(/*inc=*/SetInfo<SetType>{}, /*und=*/std::move(component));
651691
} while (to_cover.Any());
652692

@@ -695,13 +735,13 @@ class SearchCandidateFinder
695735
const ClusterIndex split = elem.und.First();
696736

697737
// Add a work item corresponding to exclusion of the split transaction.
698-
const auto& desc = m_depgraph.Descendants(split);
738+
const auto& desc = m_sorted_depgraph.Descendants(split);
699739
add_fn(/*inc=*/elem.inc,
700740
/*und=*/elem.und - desc);
701741

702742
// Add a work item corresponding to inclusion of the split transaction.
703-
const auto anc = m_depgraph.Ancestors(split) & m_todo;
704-
add_fn(/*inc=*/elem.inc.Add(m_depgraph, anc),
743+
const auto anc = m_sorted_depgraph.Ancestors(split) & m_todo;
744+
add_fn(/*inc=*/elem.inc.Add(m_sorted_depgraph, anc),
705745
/*und=*/elem.und - anc);
706746

707747
// Account for the performed split.
@@ -744,7 +784,9 @@ class SearchCandidateFinder
744784
split_fn(std::move(elem));
745785
}
746786

747-
// Return the found best set and the number of iterations performed.
787+
// Return the found best set (converted to the original transaction indices), and the
788+
// number of iterations performed.
789+
best.transactions = SortedToOriginal(best.transactions);
748790
return {std::move(best), max_iterations - iterations_left};
749791
}
750792

@@ -754,9 +796,10 @@ class SearchCandidateFinder
754796
*/
755797
void MarkDone(const SetType& done) noexcept
756798
{
757-
Assume(done.Any());
758-
Assume(done.IsSubsetOf(m_todo));
759-
m_todo -= done;
799+
const auto done_sorted = OriginalToSorted(done);
800+
Assume(done_sorted.Any());
801+
Assume(done_sorted.IsSubsetOf(m_todo));
802+
m_todo -= done_sorted;
760803
}
761804
};
762805

0 commit comments

Comments
 (0)