Skip to content

Use loser-tree merge for ConservationOfLumens - #5427

Open
drebelsky wants to merge 2 commits into
stellar:masterfrom
drebelsky:lower-col-usage
Open

Use loser-tree merge for ConservationOfLumens#5427
drebelsky wants to merge 2 commits into
stellar:masterfrom
drebelsky:lower-col-usage

Conversation

@drebelsky

Copy link
Copy Markdown
Contributor

Adapts the loser tree merge from #5252 to support the hot archive bucket list, as well. This lets us use the merge for the conservation of lumens invariant, which lowers the memory usage. On a noble dev watcher, the node no longer runs into memory problems; over the last week, memory usage (on commit 6c2ccfe) settled to 11.8–12 GB (vs 12–14 on a different watcher running 27.0.0 jammy during the same timespan).

Copilot AI balanced review requested due to automatic review settings August 21, 2026 19:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Generalizes loser-tree bucket scans to support hot archive entries and reduce ConservationOfLumens memory usage.

Changes:

  • Adds generic live/hot-archive current-entry scans.
  • Migrates the invariant to deduplicated scans.
  • Updates callbacks, indexes, and tests.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/ledger/InMemorySorobanState.cpp Adapts scan callbacks.
src/ledger/ImmutableLedgerView.h Exposes generic scans.
src/ledger/ImmutableLedgerView.cpp Delegates snapshot scans.
src/invariant/ConservationOfLumens.cpp Uses loser-tree scans.
src/bucket/test/BucketIndexTests.cpp Updates live scan tests.
src/bucket/LiveBucket.h Moves range API to base.
src/bucket/LiveBucket.cpp Removes redundant implementation.
src/bucket/HotArchiveBucketIndex.h Adds type-range lookup.
src/bucket/HotArchiveBucketIndex.cpp Implements range lookup.
src/bucket/BucketListSnapshot.h Declares generic current-entry scan.
src/bucket/BucketListSnapshot.cpp Generalizes loser-tree merging.
src/bucket/BucketBase.h Defines shared range API.
src/bucket/BucketBase.cpp Implements shared range lookup.
Suppressed comments (1)

src/bucket/BucketListSnapshot.cpp:726

  • The dependent return type also requires typename; otherwise this member declaration does not compile.
    BucketT::EntryT const&

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/bucket/BucketListSnapshot.cpp
Comment thread src/invariant/ConservationOfLumens.cpp Outdated
Comment on lines 180 to 181
// Helper function that processes an entry if it hasn't been seen before.
// Returns true on success, false on error (with error set in errorMsg).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated to remove the second half of the sentence

Comment on lines +895 to +899
static_assert(std::is_same_v<BucketT, HotArchiveBucket>,
"unexpected bucket type");
if (entry.type() == HOT_ARCHIVE_ARCHIVED)
{
if (callback(entry.archivedEntry(), key) == Loop::COMPLETE)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Comment on lines +1657 to 1658
TEST_CASE("scanForCurrentEntriesOfType randomized testing",
"[bucket][bucketindex]")

@SirTyson SirTyson left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this looks good to me! Given that the scanning primitive is subtlety different for the HotArchive vs. LiveBucketlist, I'd like to see an explicit test of the loser-tree scanning logic for the Hot Arcchive. There's also a few minor nits, but a helpful change!

void scanCurrentLiveEntriesOfType(
LedgerEntryType type,
std::function<void(LedgerEntry const&, LedgerKey const&)> callback)
std::function<Loop(LedgerEntry const&, LedgerKey const&)> callback)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, why did this change from void to loop? We see this type a lot now, it might be nice to have a typedef for it.

}

void
ImmutableLedgerView::scanCurrentHotArchiveEntriesOfType(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the change, but can we extend the iteration tests to cover the hot archive BucketList as well?

applyView.scanLiveEntriesOfType(
type, [&](BucketEntry const& be) -> Loop {
applyView.scanCurrentLiveEntriesOfType(
type, [&](LedgerEntry const& le, LedgerKey const& key) -> Loop {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Is it possible that this isStopping condition could run for a long time now? We enter the callback much less often now, so we could potentially do large batches of IO without hitting the callback in old buckets with mostly dead entries. Not a big deal, but if there's a trivial way to stop early more aggressively it might be nice, not a big deal either way.

Comment on lines +895 to +899
static_assert(std::is_same_v<BucketT, HotArchiveBucket>,
"unexpected bucket type");
if (entry.type() == HOT_ARCHIVE_ARCHIVED)
{
if (callback(entry.archivedEntry(), key) == Loop::COMPLETE)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants