-
Notifications
You must be signed in to change notification settings - Fork 116
fix(utils): update existing keys in-place in FifoCache::push #2065
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
Open
amathxbt
wants to merge
2
commits into
0xMiden:next
Choose a base branch
from
amathxbt:fix/fifo-cache-ghost-eviction-entries
base: next
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Thanks for identifying the bug. However the FIFO behaviour is still not quite right with this fix.
Every time an entry is pushed into the FIFO cache, it should be put (or moved) into the back of the eviction queue. This still doesn't happen after this fix.
I think we have two options as to how to implement this (without an O(n) scan of the eviction queue):
@Mirko-von-Leipzig any thoughts / preference?
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.
iirc this is used for the block/proofs caching for the subscriptions?
Can we not just use a
VecDequeuesince they should always be sequential by block number?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 caches are used for reads from arbitrarily connected streams. Only the starting block is "arbitrary" though. If we use just a vecdeque, we would have to peek (front()/back()) to determine whether the cache helps with the range of blocks/proofs we need.
Instead of fetch_block() it would maybe be fetch_block_range(), at least until we catch up to the tip (which should be after getting the initial range).
Do you think we should refactor it this way instead? No need for FifoCache then.
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.
What I was thinking is something like:
for additional safety we could even separate them into a cloneable Reader, and a single Writer on construction.
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.
Thanks both for the detailed feedback, this is really helpful tbh
To make sure I understand the direction before I push anything:
The plan is to drop the
HashMap+VecDequedesign entirely and replaceFifoCachewith aVecDeque<(BlockNumber, Arc<T>)>that relies on block numbers being strictly sequential.pushasserts that the incoming block is the child of the current back (or the queue is empty), pops the front when at capacity, and pushes to the back.get(number)computes the offset from the front (number - oldest) and indexes into the deque in O(1), returningNoneif the number is outside the cached range.That keeps everything O(1), avoids the ghost-entry class of bugs entirely (each block can only be inserted once, in order), and removes the need for either a linked hash map crate or a tombstone scheme.
A few clarifying points before I start:
crates/utils/src/fifo_cache.rsand keep theFifoCachename (now strictly block-keyed), or should it be renamed to something more specific likeBlockCache/SequentialCachesince it's no longer a general-purpose FIFO?FifoCacheis generic overK, V. The redesign hardcodesBlockNumberas the key. Is it fine to make it non-generic, or do you want it generic over a key type that exposes achild()andchecked_sub()(so proofs and any future sequential cache can share it)?assert_eq!(youngest.child(), number)— do you want a hardassert!(panic on misuse) or a softdebug_assert!plus a returnedResult/ silent no-op in release? Given the writer-side discipline implied by the design, I'd lean towardassert!so violations surface immediately in tests.@sergerad regarding your earlier comment about refactoring to
fetch_block_range()— should I also touch the call sites in this PR, or keep this PR focused on the cache type and do the call-site changes separately? Doing both in one PR is fine with me, just want to keep the review surface manageable.Happy to push the change as soon as you confirm the above. I'll also drop the original ghost-entry fix from this branch since the redesign makes it moot, and rewrite the CHANGELOG entry accordingly.
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.
store, so lets add it there and maybeFifoBlockCacheas a name.BlockNumberfocused for now.assert!please, just ensure its documentedThere 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.
I think we should make this change in this PR. I wouldn't want us to be performing the pop + offset logic for every get when the caller could just request a range of
[arbitrary starting block, highest cached block]via something likefetch_block_range(from: BlockNumber) -> Vec<T>.