Skip to content

Commit bbcee5a

Browse files
committed
clusterlin: improve rechunking in LinearizationChunking (optimization)
When the transactions being marked done exactly match the first chunk of what remains of the linearization, we can just remember to skip that chunk instead of computing a full rechunking. Further, chop off prefixes of the input linearization that are already done, so they don't need to be reconsidered for further rechunkings.
1 parent 04d7a04 commit bbcee5a

File tree

1 file changed

+29
-9
lines changed

1 file changed

+29
-9
lines changed

src/cluster_linearize.h

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -310,22 +310,30 @@ class LinearizationChunking
310310
/** The depgraph this linearization is for. */
311311
const DepGraph<SetType>& m_depgraph;
312312

313-
/** The linearization we started from. */
313+
/** The linearization we started from, possibly with removed prefix stripped. */
314314
Span<const ClusterIndex> m_linearization;
315315

316316
/** Chunk sets and their feerates, of what remains of the linearization. */
317317
std::vector<SetInfo<SetType>> m_chunks;
318318

319+
/** How large a prefix of m_chunks corresponds to removed transactions. */
320+
ClusterIndex m_chunks_skip{0};
321+
319322
/** Which transactions remain in the linearization. */
320323
SetType m_todo;
321324

322-
/** Fill the m_chunks variable. */
325+
/** Fill the m_chunks variable, and remove the done prefix of m_linearization. */
323326
void BuildChunks() noexcept
324327
{
325328
// Caller must clear m_chunks.
326329
Assume(m_chunks.empty());
327330

328-
// Iterate over the entries in m_linearization. This is effectively the same
331+
// Chop off the initial part of m_linearization that is already done.
332+
while (!m_linearization.empty() && !m_todo[m_linearization.front()]) {
333+
m_linearization = m_linearization.subspan(1);
334+
}
335+
336+
// Iterate over the remaining entries in m_linearization. This is effectively the same
329337
// algorithm as ChunkLinearization, but supports skipping parts of the linearization and
330338
// keeps track of the sets themselves instead of just their feerates.
331339
for (auto idx : m_linearization) {
@@ -355,13 +363,13 @@ class LinearizationChunking
355363
}
356364

357365
/** Determine how many chunks remain in the linearization. */
358-
ClusterIndex NumChunksLeft() const noexcept { return m_chunks.size(); }
366+
ClusterIndex NumChunksLeft() const noexcept { return m_chunks.size() - m_chunks_skip; }
359367

360368
/** Access a chunk. Chunk 0 is the highest-feerate prefix of what remains. */
361369
const SetInfo<SetType>& GetChunk(ClusterIndex n) const noexcept
362370
{
363-
Assume(n < m_chunks.size());
364-
return m_chunks[n];
371+
Assume(n + m_chunks_skip < m_chunks.size());
372+
return m_chunks[n + m_chunks_skip];
365373
}
366374

367375
/** Remove some subset of transactions from the linearization. */
@@ -370,9 +378,21 @@ class LinearizationChunking
370378
Assume(subset.Any());
371379
Assume(subset.IsSubsetOf(m_todo));
372380
m_todo -= subset;
373-
// Rechunk what remains of m_linearization.
374-
m_chunks.clear();
375-
BuildChunks();
381+
if (GetChunk(0).transactions == subset) {
382+
// If the newly done transactions exactly match the first chunk of the remainder of
383+
// the linearization, we do not need to rechunk; just remember to skip one
384+
// additional chunk.
385+
++m_chunks_skip;
386+
// With subset marked done, some prefix of m_linearization will be done now. How long
387+
// that prefix is depends on how many done elements were interspersed with subset,
388+
// but at least as many transactions as there are in subset.
389+
m_linearization = m_linearization.subspan(subset.Count());
390+
} else {
391+
// Otherwise rechunk what remains of m_linearization.
392+
m_chunks.clear();
393+
m_chunks_skip = 0;
394+
BuildChunks();
395+
}
376396
}
377397

378398
/** Find the shortest intersection between subset and the prefixes of remaining chunks

0 commit comments

Comments
 (0)