-
Notifications
You must be signed in to change notification settings - Fork 30
LedgerDB: prune on garbage collection instead of on every change #1513
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
8b48bb3
to
045f1cc
Compare
13e5533
to
68402ed
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Storage/LedgerDB/V2.hs
Show resolved
Hide resolved
981971e
to
0c5b137
Compare
68402ed
to
4d6fd67
Compare
0c5b137
to
7900088
Compare
4d6fd67
to
7049fd4
Compare
Sync benchmarks are looking good (mainnet, first 1e6 slots/blocks): LMDB benchmark (of course, this is a bit degenerate as Byron doesn't have tables, but this still serves as a regression test for the Note that d1b6215 is crucial; otherwise, there is a significant (2x) regression in max heap size. |
2e01b1c
to
b9e25f5
Compare
19faf20
to
4010598
Compare
b9e25f5
to
894940c
Compare
894940c
to
a8fa7e2
Compare
ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Storage/LedgerDB/API.hs
Outdated
Show resolved
Hide resolved
...ros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Storage/LedgerDB/V1/DbChangelog.hs
Outdated
Show resolved
Hide resolved
...ros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Storage/LedgerDB/V1/DbChangelog.hs
Outdated
Show resolved
Hide resolved
...boros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Storage/LedgerDB/V2/LedgerSeq.hs
Outdated
Show resolved
Hide resolved
a8fa7e2
to
b503dc3
Compare
ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Storage/LedgerDB/API.hs
Show resolved
Hide resolved
ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Storage/LedgerDB/API.hs
Outdated
Show resolved
Hide resolved
ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Storage/LedgerDB/V1.hs
Outdated
Show resolved
Hide resolved
ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Storage/LedgerDB/V1.hs
Show resolved
Hide resolved
...ros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Storage/ChainDB/Impl/Background.hs
Outdated
Show resolved
Hide resolved
@@ -0,0 +1,6 @@ | |||
### Breaking | |||
|
|||
- Changed pruning of immutable ledger states to happen on LedgerDB/ChainDB |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changelog entry here seems misleading, but please correct me if I'm wrong.
If I understand correctly, we are now pruning the LedgerDB in copyAndSnapshotRunner
, i.e. when moving blocks from VolatileDB to ImmutableDB. In the scheduled ChainDB GCs, we will not prune the LedgerDB at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, I removed the "ChainDB" part here (it happens as part of LedgerDB garbage collection, which we execute as part of the copyAndSnapshot
background thread in the ChainDB 👍)
Based on this discussion and your justified confusion in #1513 (comment): Maybe we actually want to have a separate ChainDB background thread that does LedgerDB snapshotting + pruning?
-
Pro: clearer separation of concerns; taking a snapshot does not block copying blocks to the ImmutableDB (this improvement is independent of this PR)
Especially the latter point might be more relevant with Optional random delay when creating snapshots #1573
-
Con: more ceremony, more threads mean more RTS contention (seems weak)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FTR we discussed this in the sync today, and decided that a new ChainDB background thread makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in d1b6215
b503dc3
to
6c78fad
Compare
Thanks for the great reviews, I hope I addressed your comments. Interesting changes:
|
6c78fad
to
48bb1fe
Compare
It is not necessary to perform the garbage collection of the LedgerDB and the map of invalid blocks in the same STM transaction. In the past, this was important, but it is not anymore, see #1507.
Primarily, this is an optimization to reduce the maximum memory usage (more relevant with the in-memory backend) when pruning happens on garbage collection instead of while adding new blocks to the LedgerDB, see the added commit and the benchmark in the pull request. Previously, LedgerDB garbage collection happened as part of VolatileDB garbage collection, which was intentionally rate-limited. Also, it resolves the current (somewhat weird) behavior that we do not copy any blocks to the ImmutableDB when we are taking a snapshot (which can take >2 minutes), and consequently also not garbage-collecting the VolatileDB. It also synergizes with the planned feature to add a random delay when taking snapshots.
Also make sure to account for the fact that the DbChangelog might have gotten pruned between opening and committing the forker.
regarding the previous few commits
It was already superseded in the most important places due to `LedgerDbPruneBeforeSlot`. Its remaining use cases are non-essential: - Replay on startup. In this case, we never roll back, so not maintaining k states is actually an optimization here. We can also remove the now-redundant `InitDB.pruneDb` function. - Internal functions used for db-analyser. Here, we can just as well use `LedgerDbPruneAll` (which is used by `pruneToImmTipOnly`) as we never need to roll back. - Testing. In particular, we remove some DbChangelog tests that previously ensured that only at most @k@ states are kept. This is now no longer true; that property is instead enforced by the LedgerDB built on top of the DbChangelog. A follow-up commit in this PR enriches the LedgerDB state machine test to make sure that the public API functions behave appropriately, ensuring that we don't lose test coverage (and also testing V2, which previously didn't have any such tests).
Make sure that we correctly fail when trying to roll back too far.
48bb1fe
to
ad7acfa
Compare
This is in preparation for #1424
This PR is intended to be reviewed commit-by-commit.
Currently, we prune the LedgerDB (ie remove all but the last
k+1
states) every time we adopt a longer chain. This means that we can not rely on the fact that other threads (like thecopyAndSnapshot
ChainDB background) actually observe all immutable ledger states, just as described in the caveats of ourWatcher
abstraction.However, a predictable ledger snapshotting rule (#1424) requires this property; otherwise, when the node is under high load and/or we are adopting multiple blocks in quick succession, the node might not be able to create a snapshot for its desired block.
This PR changes this fact: Now, when adopting new blocks, the LedgerDB is not immediately pruned. Instead, the a new dedicated background thread for ledger maintenance tasks (flushing/snapshotting/garbage collection) in the ChainDB will periodically (on every new immutable block) wake up and (in particular) garbage collect the LedgerDB based on a slot number.
Also, this makes the semantics more consistent with the existing garbage collection of previously-applied blocks in the LedgerDB, and also with how the ChainDB works, where we also don't immediately delete blocks from the VolatileDB once they are buried beneath
k+1
blocks.See #1513 (comment) for benchmarks demonstrating that the peak memory usage does not increase while syncing (where we now briefly might hold more than
k+1
ledger states in memory).