mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 23:09:44 -04:00
txgraph: Reuse discarded chunkindex entries (optimization)
This commit is contained in:
parent
82054fa25f
commit
e3d3ad9723
1 changed files with 49 additions and 22 deletions
|
@ -9,6 +9,7 @@
|
||||||
#include <util/bitset.h>
|
#include <util/bitset.h>
|
||||||
#include <util/check.h>
|
#include <util/check.h>
|
||||||
#include <util/feefrac.h>
|
#include <util/feefrac.h>
|
||||||
|
#include <util/vector.h>
|
||||||
|
|
||||||
#include <compare>
|
#include <compare>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -312,6 +313,8 @@ private:
|
||||||
ChunkIndex m_main_chunkindex;
|
ChunkIndex m_main_chunkindex;
|
||||||
/** Number of index-observing objects in existence (BlockBuilderImpls). */
|
/** Number of index-observing objects in existence (BlockBuilderImpls). */
|
||||||
size_t m_main_chunkindex_observers{0};
|
size_t m_main_chunkindex_observers{0};
|
||||||
|
/** Cache of discarded ChunkIndex node handles to re-use, avoiding additional allocation. */
|
||||||
|
std::vector<ChunkIndex::node_type> m_main_chunkindex_discarded;
|
||||||
|
|
||||||
/** A Locator that describes whether, where, and in which Cluster an Entry appears.
|
/** A Locator that describes whether, where, and in which Cluster an Entry appears.
|
||||||
* Every Entry has MAX_LEVELS locators, as it may appear in one Cluster per level.
|
* Every Entry has MAX_LEVELS locators, as it may appear in one Cluster per level.
|
||||||
|
@ -431,6 +434,10 @@ public:
|
||||||
void ClearLocator(int level, GraphIndex index) noexcept;
|
void ClearLocator(int level, GraphIndex index) noexcept;
|
||||||
/** Find which Clusters in main conflict with ones in staging. */
|
/** Find which Clusters in main conflict with ones in staging. */
|
||||||
std::vector<Cluster*> GetConflicts() const noexcept;
|
std::vector<Cluster*> GetConflicts() const noexcept;
|
||||||
|
/** Clear an Entry's ChunkData. */
|
||||||
|
void ClearChunkData(Entry& entry) noexcept;
|
||||||
|
/** Give an Entry a ChunkData object. */
|
||||||
|
void CreateChunkData(GraphIndex idx, LinearizationIndex chunk_count) noexcept;
|
||||||
|
|
||||||
// Functions for handling Refs.
|
// Functions for handling Refs.
|
||||||
|
|
||||||
|
@ -584,6 +591,37 @@ public:
|
||||||
void Skip() noexcept final;
|
void Skip() noexcept final;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void TxGraphImpl::ClearChunkData(Entry& entry) noexcept
|
||||||
|
{
|
||||||
|
if (entry.m_main_chunkindex_iterator != m_main_chunkindex.end()) {
|
||||||
|
Assume(m_main_chunkindex_observers == 0);
|
||||||
|
// If the Entry has a non-empty m_main_chunkindex_iterator, extract it, and move the handle
|
||||||
|
// to the cache of discarded chunkindex entries.
|
||||||
|
m_main_chunkindex_discarded.emplace_back(m_main_chunkindex.extract(entry.m_main_chunkindex_iterator));
|
||||||
|
entry.m_main_chunkindex_iterator = m_main_chunkindex.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TxGraphImpl::CreateChunkData(GraphIndex idx, LinearizationIndex chunk_count) noexcept
|
||||||
|
{
|
||||||
|
auto& entry = m_entries[idx];
|
||||||
|
if (!m_main_chunkindex_discarded.empty()) {
|
||||||
|
// Reuse an discarded node handle.
|
||||||
|
auto& node = m_main_chunkindex_discarded.back().value();
|
||||||
|
node.m_graph_index = idx;
|
||||||
|
node.m_chunk_count = chunk_count;
|
||||||
|
auto insert_result = m_main_chunkindex.insert(std::move(m_main_chunkindex_discarded.back()));
|
||||||
|
Assume(insert_result.inserted);
|
||||||
|
entry.m_main_chunkindex_iterator = insert_result.position;
|
||||||
|
m_main_chunkindex_discarded.pop_back();
|
||||||
|
} else {
|
||||||
|
// Construct a new entry.
|
||||||
|
auto emplace_result = m_main_chunkindex.emplace(idx, chunk_count);
|
||||||
|
Assume(emplace_result.second);
|
||||||
|
entry.m_main_chunkindex_iterator = emplace_result.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TxGraphImpl::ClearLocator(int level, GraphIndex idx) noexcept
|
void TxGraphImpl::ClearLocator(int level, GraphIndex idx) noexcept
|
||||||
{
|
{
|
||||||
auto& entry = m_entries[idx];
|
auto& entry = m_entries[idx];
|
||||||
|
@ -606,11 +644,7 @@ void TxGraphImpl::ClearLocator(int level, GraphIndex idx) noexcept
|
||||||
--m_staging_clusterset->m_txcount;
|
--m_staging_clusterset->m_txcount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (level == 0 && entry.m_main_chunkindex_iterator != m_main_chunkindex.end()) {
|
if (level == 0) ClearChunkData(entry);
|
||||||
Assume(m_main_chunkindex_observers == 0);
|
|
||||||
m_main_chunkindex.erase(entry.m_main_chunkindex_iterator);
|
|
||||||
entry.m_main_chunkindex_iterator = m_main_chunkindex.end();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cluster::Updated(TxGraphImpl& graph) noexcept
|
void Cluster::Updated(TxGraphImpl& graph) noexcept
|
||||||
|
@ -618,13 +652,9 @@ void Cluster::Updated(TxGraphImpl& graph) noexcept
|
||||||
// Update all the Locators for this Cluster's Entry objects.
|
// Update all the Locators for this Cluster's Entry objects.
|
||||||
for (DepGraphIndex idx : m_linearization) {
|
for (DepGraphIndex idx : m_linearization) {
|
||||||
auto& entry = graph.m_entries[m_mapping[idx]];
|
auto& entry = graph.m_entries[m_mapping[idx]];
|
||||||
if (m_level == 0 && entry.m_main_chunkindex_iterator != graph.m_main_chunkindex.end()) {
|
// Discard any potential ChunkData prior to modifying the Cluster (as that could
|
||||||
// Destroy any potential ChunkData prior to modifying the Cluster (as that could
|
|
||||||
// invalidate its ordering).
|
// invalidate its ordering).
|
||||||
Assume(graph.m_main_chunkindex_observers == 0);
|
if (m_level == 0) graph.ClearChunkData(entry);
|
||||||
graph.m_main_chunkindex.erase(entry.m_main_chunkindex_iterator);
|
|
||||||
entry.m_main_chunkindex_iterator = graph.m_main_chunkindex.end();
|
|
||||||
}
|
|
||||||
entry.m_locator[m_level].SetPresent(this, idx);
|
entry.m_locator[m_level].SetPresent(this, idx);
|
||||||
}
|
}
|
||||||
// If this is for the main graph (level = 0), and the Cluster's quality is ACCEPTABLE or
|
// If this is for the main graph (level = 0), and the Cluster's quality is ACCEPTABLE or
|
||||||
|
@ -651,9 +681,7 @@ void Cluster::Updated(TxGraphImpl& graph) noexcept
|
||||||
chunk.transactions.Reset(idx);
|
chunk.transactions.Reset(idx);
|
||||||
if (chunk.transactions.None()) {
|
if (chunk.transactions.None()) {
|
||||||
// Last transaction in the chunk.
|
// Last transaction in the chunk.
|
||||||
auto [it, inserted] = graph.m_main_chunkindex.emplace(graph_idx, chunk_count);
|
graph.CreateChunkData(graph_idx, chunk_count);
|
||||||
Assume(inserted);
|
|
||||||
entry.m_main_chunkindex_iterator = it;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -912,13 +940,9 @@ void Cluster::Merge(TxGraphImpl& graph, Cluster& other) noexcept
|
||||||
// feerates, as Updated() will be invoked by Cluster::ApplyDependencies on the resulting
|
// feerates, as Updated() will be invoked by Cluster::ApplyDependencies on the resulting
|
||||||
// merged Cluster later anyway).
|
// merged Cluster later anyway).
|
||||||
auto& entry = graph.m_entries[idx];
|
auto& entry = graph.m_entries[idx];
|
||||||
if (m_level == 0 && entry.m_main_chunkindex_iterator != graph.m_main_chunkindex.end()) {
|
// Discard any potential ChunkData prior to modifying the Cluster (as that could
|
||||||
// Destroy any potential ChunkData prior to modifying the Cluster (as that could
|
|
||||||
// invalidate its ordering).
|
// invalidate its ordering).
|
||||||
Assume(graph.m_main_chunkindex_observers == 0);
|
if (m_level == 0) graph.ClearChunkData(entry);
|
||||||
graph.m_main_chunkindex.erase(entry.m_main_chunkindex_iterator);
|
|
||||||
entry.m_main_chunkindex_iterator = graph.m_main_chunkindex.end();
|
|
||||||
}
|
|
||||||
entry.m_locator[m_level].SetPresent(this, new_pos);
|
entry.m_locator[m_level].SetPresent(this, new_pos);
|
||||||
}
|
}
|
||||||
// Purge the other Cluster, now that everything has been moved.
|
// Purge the other Cluster, now that everything has been moved.
|
||||||
|
@ -1161,6 +1185,9 @@ void TxGraphImpl::Compact() noexcept
|
||||||
if (!m_staging_clusterset->m_removed.empty()) return;
|
if (!m_staging_clusterset->m_removed.empty()) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Release memory used by discarded ChunkData index entries.
|
||||||
|
ClearShrink(m_main_chunkindex_discarded);
|
||||||
|
|
||||||
// Sort the GraphIndexes that need to be cleaned up. They are sorted in reverse, so the last
|
// Sort the GraphIndexes that need to be cleaned up. They are sorted in reverse, so the last
|
||||||
// ones get processed first. This means earlier-processed GraphIndexes will not cause moving of
|
// ones get processed first. This means earlier-processed GraphIndexes will not cause moving of
|
||||||
// later-processed ones during the "swap with end of m_entries" step below (which might
|
// later-processed ones during the "swap with end of m_entries" step below (which might
|
||||||
|
|
Loading…
Add table
Reference in a new issue