Skip to content

Commit bb5cb22

Browse files
sipal0rinc
andcommitted
depgraph: add memory usage control (feature)
Co-Authored-By: Lőrinc <[email protected]>
1 parent b1637a9 commit bb5cb22

File tree

2 files changed

+72
-51
lines changed

2 files changed

+72
-51
lines changed

src/cluster_linearize.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <utility>
1313
#include <vector>
1414

15+
#include <memusage.h>
1516
#include <random.h>
1617
#include <span.h>
1718
#include <util/feefrac.h>
@@ -332,6 +333,17 @@ class DepGraph
332333
}
333334
return true;
334335
}
336+
337+
/** Reduce memory usage if possible. No observable effect. */
338+
void Compact() noexcept
339+
{
340+
entries.shrink_to_fit();
341+
}
342+
343+
size_t DynamicMemoryUsage() const noexcept
344+
{
345+
return memusage::DynamicUsage(entries);
346+
}
335347
};
336348

337349
/** A set of transactions together with their aggregate feerate. */

src/test/fuzz/cluster_linearize.cpp

Lines changed: 60 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -452,63 +452,72 @@ FUZZ_TARGET(clusterlin_depgraph_sim)
452452
}
453453
};
454454

455+
auto last_compaction_pos{real.PositionRange()};
456+
455457
LIMITED_WHILE(provider.remaining_bytes() > 0, 1000) {
456-
uint8_t command = provider.ConsumeIntegral<uint8_t>();
457-
if (num_tx_sim == 0 || ((command % 3) <= 0 && num_tx_sim < TestBitSet::Size())) {
458-
// AddTransaction.
459-
auto fee = provider.ConsumeIntegralInRange<int64_t>(-0x8000000000000, 0x7ffffffffffff);
460-
auto size = provider.ConsumeIntegralInRange<int32_t>(1, 0x3fffff);
461-
FeeFrac feerate{fee, size};
462-
// Apply to DepGraph.
463-
auto idx = real.AddTransaction(feerate);
464-
// Verify that the returned index is correct.
465-
assert(!sim[idx].has_value());
466-
for (DepGraphIndex i = 0; i < TestBitSet::Size(); ++i) {
467-
if (!sim[i].has_value()) {
468-
assert(idx == i);
469-
break;
458+
int command = provider.ConsumeIntegral<uint8_t>() % 4;
459+
while (true) {
460+
// Iterate decreasing command until an applicable branch is found.
461+
if (num_tx_sim < TestBitSet::Size() && command-- == 0) {
462+
// AddTransaction.
463+
auto fee = provider.ConsumeIntegralInRange<int64_t>(-0x8000000000000, 0x7ffffffffffff);
464+
auto size = provider.ConsumeIntegralInRange<int32_t>(1, 0x3fffff);
465+
FeeFrac feerate{fee, size};
466+
// Apply to DepGraph.
467+
auto idx = real.AddTransaction(feerate);
468+
// Verify that the returned index is correct.
469+
assert(!sim[idx].has_value());
470+
for (DepGraphIndex i = 0; i < TestBitSet::Size(); ++i) {
471+
if (!sim[i].has_value()) {
472+
assert(idx == i);
473+
break;
474+
}
470475
}
471-
}
472-
// Update sim.
473-
sim[idx] = {feerate, TestBitSet::Singleton(idx)};
474-
++num_tx_sim;
475-
continue;
476-
}
477-
if ((command % 3) <= 1 && num_tx_sim > 0) {
478-
// AddDependencies.
479-
DepGraphIndex child = idx_fn();
480-
auto parents = subset_fn();
481-
// Apply to DepGraph.
482-
real.AddDependencies(parents, child);
483-
// Apply to sim.
484-
sim[child]->second |= parents;
485-
continue;
486-
}
487-
if (num_tx_sim > 0) {
488-
// Remove transactions.
489-
auto del = set_fn();
490-
// Propagate all ancestry information before deleting anything in the simulation (as
491-
// intermediary transactions may be deleted which impact connectivity).
492-
anc_update_fn();
493-
// Compare the state of the transactions being deleted.
494-
for (auto i : del) check_fn(i);
495-
// Apply to DepGraph.
496-
real.RemoveTransactions(del);
497-
// Apply to sim.
498-
for (DepGraphIndex i = 0; i < sim.size(); ++i) {
499-
if (sim[i].has_value()) {
500-
if (del[i]) {
501-
--num_tx_sim;
502-
sim[i] = std::nullopt;
503-
} else {
504-
sim[i]->second -= del;
476+
// Update sim.
477+
sim[idx] = {feerate, TestBitSet::Singleton(idx)};
478+
++num_tx_sim;
479+
break;
480+
} else if (num_tx_sim > 0 && command-- == 0) {
481+
// AddDependencies.
482+
DepGraphIndex child = idx_fn();
483+
auto parents = subset_fn();
484+
// Apply to DepGraph.
485+
real.AddDependencies(parents, child);
486+
// Apply to sim.
487+
sim[child]->second |= parents;
488+
break;
489+
} else if (num_tx_sim > 0 && command-- == 0) {
490+
// Remove transactions.
491+
auto del = set_fn();
492+
// Propagate all ancestry information before deleting anything in the simulation (as
493+
// intermediary transactions may be deleted which impact connectivity).
494+
anc_update_fn();
495+
// Compare the state of the transactions being deleted.
496+
for (auto i : del) check_fn(i);
497+
// Apply to DepGraph.
498+
real.RemoveTransactions(del);
499+
// Apply to sim.
500+
for (DepGraphIndex i = 0; i < sim.size(); ++i) {
501+
if (sim[i].has_value()) {
502+
if (del[i]) {
503+
--num_tx_sim;
504+
sim[i] = std::nullopt;
505+
} else {
506+
sim[i]->second -= del;
507+
}
505508
}
506509
}
510+
break;
511+
} else if (command-- == 0) {
512+
// Compact.
513+
const size_t mem_before{real.DynamicMemoryUsage()};
514+
real.Compact();
515+
const size_t mem_after{real.DynamicMemoryUsage()};
516+
assert(real.PositionRange() < last_compaction_pos ? mem_after < mem_before : mem_after <= mem_before);
517+
last_compaction_pos = real.PositionRange();
518+
break;
507519
}
508-
continue;
509520
}
510-
// This should be unreachable (one of the 3 above actions should always be possible).
511-
assert(false);
512521
}
513522

514523
// Compare the real obtained depgraph against the simulation.

0 commit comments

Comments
 (0)