@@ -734,6 +734,15 @@ void TxGraphImpl::GroupClusters() noexcept
734
734
std::sort (an_clusters.begin (), an_clusters.end ());
735
735
an_clusters.erase (std::unique (an_clusters.begin (), an_clusters.end ()), an_clusters.end ());
736
736
737
+ // Sort the dependencies by child Cluster.
738
+ std::sort (m_deps_to_add.begin (), m_deps_to_add.end (), [&](auto & a, auto & b) noexcept {
739
+ auto [_a_par, a_chl] = a;
740
+ auto [_b_par, b_chl] = b;
741
+ auto a_chl_cluster = m_entries[a_chl].m_locator .cluster ;
742
+ auto b_chl_cluster = m_entries[b_chl].m_locator .cluster ;
743
+ return std::less{}(a_chl_cluster, b_chl_cluster);
744
+ });
745
+
737
746
// Run the union-find algorithm to to find partitions of the input Clusters which need to be
738
747
// grouped together. See https://en.wikipedia.org/wiki/Disjoint-set_data_structure.
739
748
{
@@ -813,25 +822,29 @@ void TxGraphImpl::GroupClusters() noexcept
813
822
// Populate the an_clusters and an_deps data structures with the list of input Clusters,
814
823
// and the input dependencies, annotated with the representative of the Cluster partition
815
824
// it applies to.
825
+ an_deps.reserve (m_deps_to_add.size ());
826
+ auto deps_it = m_deps_to_add.begin ();
816
827
for (size_t i = 0 ; i < partition_data.size (); ++i) {
817
828
auto & data = partition_data[i];
818
829
// Find the representative of the partition Cluster i is in, and store it with the
819
830
// Cluster.
820
831
auto rep = find_root_fn (&data)->cluster ;
821
832
Assume (an_clusters[i].second == nullptr );
822
833
an_clusters[i].second = rep;
823
- }
824
- an_deps.reserve (m_deps_to_add.size ());
825
- for (auto [par, chl] : m_deps_to_add) {
826
- auto chl_cluster = m_entries[chl].m_locator .cluster ;
827
- auto par_cluster = m_entries[par].m_locator .cluster ;
828
- // Nothing to do if either parent or child transaction is removed already.
829
- if (par_cluster == nullptr || chl_cluster == nullptr ) continue ;
830
- // Find the representative of the partition which this dependency's child is in (which
831
- // should be the same as the one for the parent).
832
- auto rep = find_root_fn (locate_fn (chl_cluster))->cluster ;
833
- // Create an_deps entry.
834
- an_deps.emplace_back (std::pair{par, chl}, rep);
834
+ // Find all dependencies whose child Cluster is Cluster i, and annotate them with rep.
835
+ while (deps_it != m_deps_to_add.end ()) {
836
+ auto [par, chl] = *deps_it;
837
+ auto chl_cluster = m_entries[chl].m_locator .cluster ;
838
+ if (std::greater{}(chl_cluster, data.cluster )) break ;
839
+ // Skip dependencies that apply to earlier Clusters (those necessary are for
840
+ // deleted transactions, as otherwise we'd have processed them already).
841
+ if (chl_cluster == data.cluster ) {
842
+ auto par_cluster = m_entries[par].m_locator .cluster ;
843
+ // Also filter out dependencies applying to a removed parent.
844
+ if (par_cluster != nullptr ) an_deps.emplace_back (*deps_it, rep);
845
+ }
846
+ ++deps_it;
847
+ }
835
848
}
836
849
}
837
850
0 commit comments