@@ -310,22 +310,30 @@ class LinearizationChunking
310
310
/* * The depgraph this linearization is for. */
311
311
const DepGraph<SetType>& m_depgraph;
312
312
313
- /* * The linearization we started from. */
313
+ /* * The linearization we started from, possibly with removed prefix stripped . */
314
314
Span<const ClusterIndex> m_linearization;
315
315
316
316
/* * Chunk sets and their feerates, of what remains of the linearization. */
317
317
std::vector<SetInfo<SetType>> m_chunks;
318
318
319
+ /* * How large a prefix of m_chunks corresponds to removed transactions. */
320
+ ClusterIndex m_chunks_skip{0 };
321
+
319
322
/* * Which transactions remain in the linearization. */
320
323
SetType m_todo;
321
324
322
- /* * Fill the m_chunks variable. */
325
+ /* * Fill the m_chunks variable, and remove the done prefix of m_linearization . */
323
326
void BuildChunks () noexcept
324
327
{
325
328
// Caller must clear m_chunks.
326
329
Assume (m_chunks.empty ());
327
330
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
329
337
// algorithm as ChunkLinearization, but supports skipping parts of the linearization and
330
338
// keeps track of the sets themselves instead of just their feerates.
331
339
for (auto idx : m_linearization) {
@@ -355,13 +363,13 @@ class LinearizationChunking
355
363
}
356
364
357
365
/* * 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 ; }
359
367
360
368
/* * Access a chunk. Chunk 0 is the highest-feerate prefix of what remains. */
361
369
const SetInfo<SetType>& GetChunk (ClusterIndex n) const noexcept
362
370
{
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 ];
365
373
}
366
374
367
375
/* * Remove some subset of transactions from the linearization. */
@@ -370,9 +378,21 @@ class LinearizationChunking
370
378
Assume (subset.Any ());
371
379
Assume (subset.IsSubsetOf (m_todo));
372
380
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
+ }
376
396
}
377
397
378
398
/* * Find the shortest intersection between subset and the prefixes of remaining chunks
0 commit comments