mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 14:59:39 -04:00
txgraph: track amount of work done in linearization (preparation)
This commit is contained in:
parent
eb5f4db166
commit
b074308e6f
4 changed files with 30 additions and 22 deletions
|
@ -229,8 +229,8 @@ void BenchLinearizeOptimally(benchmark::Bench& bench, const std::array<uint8_t,
|
|||
reader >> Using<DepGraphFormatter>(depgraph);
|
||||
uint64_t rng_seed = 0;
|
||||
bench.run([&] {
|
||||
auto res = Linearize(depgraph, /*max_iterations=*/10000000, rng_seed++);
|
||||
assert(res.second);
|
||||
auto [_lin, optimal, _cost] = Linearize(depgraph, /*max_iterations=*/10000000, rng_seed++);
|
||||
assert(optimal);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -1030,19 +1030,20 @@ public:
|
|||
* linearize.
|
||||
* @param[in] old_linearization An existing linearization for the cluster (which must be
|
||||
* topologically valid), or empty.
|
||||
* @return A pair of:
|
||||
* @return A tuple of:
|
||||
* - The resulting linearization. It is guaranteed to be at least as
|
||||
* good (in the feerate diagram sense) as old_linearization.
|
||||
* - A boolean indicating whether the result is guaranteed to be
|
||||
* optimal.
|
||||
* - How many optimization steps were actually performed.
|
||||
*
|
||||
* Complexity: possibly O(N * min(max_iterations + N, sqrt(2^N))) where N=depgraph.TxCount().
|
||||
*/
|
||||
template<typename SetType>
|
||||
std::pair<std::vector<DepGraphIndex>, bool> Linearize(const DepGraph<SetType>& depgraph, uint64_t max_iterations, uint64_t rng_seed, std::span<const DepGraphIndex> old_linearization = {}) noexcept
|
||||
std::tuple<std::vector<DepGraphIndex>, bool, uint64_t> Linearize(const DepGraph<SetType>& depgraph, uint64_t max_iterations, uint64_t rng_seed, std::span<const DepGraphIndex> old_linearization = {}) noexcept
|
||||
{
|
||||
Assume(old_linearization.empty() || old_linearization.size() == depgraph.TxCount());
|
||||
if (depgraph.TxCount() == 0) return {{}, true};
|
||||
if (depgraph.TxCount() == 0) return {{}, true, 0};
|
||||
|
||||
uint64_t iterations_left = max_iterations;
|
||||
std::vector<DepGraphIndex> linearization;
|
||||
|
@ -1113,7 +1114,7 @@ std::pair<std::vector<DepGraphIndex>, bool> Linearize(const DepGraph<SetType>& d
|
|||
}
|
||||
}
|
||||
|
||||
return {std::move(linearization), optimal};
|
||||
return {std::move(linearization), optimal, max_iterations - iterations_left};
|
||||
}
|
||||
|
||||
/** Improve a given linearization.
|
||||
|
|
|
@ -906,7 +906,8 @@ FUZZ_TARGET(clusterlin_linearize)
|
|||
|
||||
// Invoke Linearize().
|
||||
iter_count &= 0x7ffff;
|
||||
auto [linearization, optimal] = Linearize(depgraph, iter_count, rng_seed, old_linearization);
|
||||
auto [linearization, optimal, cost] = Linearize(depgraph, iter_count, rng_seed, old_linearization);
|
||||
assert(cost <= iter_count);
|
||||
SanityCheck(depgraph, linearization);
|
||||
auto chunking = ChunkLinearization(depgraph, linearization);
|
||||
|
||||
|
@ -1090,7 +1091,7 @@ FUZZ_TARGET(clusterlin_postlinearize_tree)
|
|||
|
||||
// Try to find an even better linearization directly. This must not change the diagram for the
|
||||
// same reason.
|
||||
auto [opt_linearization, _optimal] = Linearize(depgraph_tree, 100000, rng_seed, post_linearization);
|
||||
auto [opt_linearization, _optimal, _cost] = Linearize(depgraph_tree, 100000, rng_seed, post_linearization);
|
||||
auto opt_chunking = ChunkLinearization(depgraph_tree, opt_linearization);
|
||||
auto cmp_opt = CompareChunks(opt_chunking, post_chunking);
|
||||
assert(cmp_opt == 0);
|
||||
|
|
|
@ -181,8 +181,8 @@ public:
|
|||
void Merge(TxGraphImpl& graph, Cluster& cluster) noexcept;
|
||||
/** Given a span of (parent, child) pairs that all belong to this Cluster, apply them. */
|
||||
void ApplyDependencies(TxGraphImpl& graph, std::span<std::pair<GraphIndex, GraphIndex>> to_apply) noexcept;
|
||||
/** Improve the linearization of this Cluster. */
|
||||
void Relinearize(TxGraphImpl& graph, uint64_t max_iters) noexcept;
|
||||
/** Improve the linearization of this Cluster. Returns how much work was performed. */
|
||||
uint64_t Relinearize(TxGraphImpl& graph, uint64_t max_iters) noexcept;
|
||||
/** For every chunk in the cluster, append its FeeFrac to ret. */
|
||||
void AppendChunkFeerates(std::vector<FeeFrac>& ret) const noexcept;
|
||||
/** Add a TrimTxData entry for every transaction in the Cluster to ret. Implicit dependencies
|
||||
|
@ -561,10 +561,11 @@ public:
|
|||
void Merge(std::span<Cluster*> to_merge) noexcept;
|
||||
/** Apply all m_deps_to_add to the relevant Clusters in the specified level. */
|
||||
void ApplyDependencies(int level) noexcept;
|
||||
/** Make a specified Cluster have quality ACCEPTABLE or OPTIMAL. */
|
||||
void MakeAcceptable(Cluster& cluster) noexcept;
|
||||
/** Make all Clusters at the specified level have quality ACCEPTABLE or OPTIMAL. */
|
||||
void MakeAllAcceptable(int level) noexcept;
|
||||
/** Make a specified Cluster have quality ACCEPTABLE or OPTIMAL. Return how much work was performed. */
|
||||
uint64_t MakeAcceptable(Cluster& cluster) noexcept;
|
||||
/** Make all Clusters at the specified level have quality ACCEPTABLE or OPTIMAL. Return how much
|
||||
* was performed. */
|
||||
uint64_t MakeAllAcceptable(int level) noexcept;
|
||||
|
||||
// Implementations for the public TxGraph interface.
|
||||
|
||||
|
@ -1643,15 +1644,15 @@ void TxGraphImpl::ApplyDependencies(int level) noexcept
|
|||
clusterset.m_group_data = GroupData{};
|
||||
}
|
||||
|
||||
void Cluster::Relinearize(TxGraphImpl& graph, uint64_t max_iters) noexcept
|
||||
uint64_t Cluster::Relinearize(TxGraphImpl& graph, uint64_t max_iters) noexcept
|
||||
{
|
||||
// We can only relinearize Clusters that do not need splitting.
|
||||
Assume(!NeedsSplitting());
|
||||
// No work is required for Clusters which are already optimally linearized.
|
||||
if (IsOptimal()) return;
|
||||
if (IsOptimal()) return 0;
|
||||
// Invoke the actual linearization algorithm (passing in the existing one).
|
||||
uint64_t rng_seed = graph.m_rng.rand64();
|
||||
auto [linearization, optimal] = Linearize(m_depgraph, max_iters, rng_seed, m_linearization);
|
||||
auto [linearization, optimal, cost] = Linearize(m_depgraph, max_iters, rng_seed, m_linearization);
|
||||
// Postlinearize if the result isn't optimal already. This guarantees (among other things)
|
||||
// that the chunks of the resulting linearization are all connected.
|
||||
if (!optimal) PostLinearize(m_depgraph, linearization);
|
||||
|
@ -1662,25 +1663,30 @@ void Cluster::Relinearize(TxGraphImpl& graph, uint64_t max_iters) noexcept
|
|||
graph.SetClusterQuality(m_level, m_quality, m_setindex, new_quality);
|
||||
// Update the Entry objects.
|
||||
Updated(graph);
|
||||
return cost;
|
||||
}
|
||||
|
||||
void TxGraphImpl::MakeAcceptable(Cluster& cluster) noexcept
|
||||
uint64_t TxGraphImpl::MakeAcceptable(Cluster& cluster) noexcept
|
||||
{
|
||||
uint64_t cost{0};
|
||||
// Relinearize the Cluster if needed.
|
||||
if (!cluster.NeedsSplitting() && !cluster.IsAcceptable() && !cluster.IsOversized()) {
|
||||
cluster.Relinearize(*this, 10000);
|
||||
cost += cluster.Relinearize(*this, 10000);
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
void TxGraphImpl::MakeAllAcceptable(int level) noexcept
|
||||
uint64_t TxGraphImpl::MakeAllAcceptable(int level) noexcept
|
||||
{
|
||||
ApplyDependencies(level);
|
||||
auto& clusterset = GetClusterSet(level);
|
||||
if (clusterset.m_oversized == true) return;
|
||||
if (clusterset.m_oversized == true) return 0;
|
||||
auto& queue = clusterset.m_clusters[int(QualityLevel::NEEDS_RELINEARIZE)];
|
||||
uint64_t cost{0};
|
||||
while (!queue.empty()) {
|
||||
MakeAcceptable(*queue.back().get());
|
||||
cost += MakeAcceptable(*queue.back().get());
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
Cluster::Cluster(uint64_t sequence) noexcept : m_sequence{sequence} {}
|
||||
|
|
Loading…
Add table
Reference in a new issue