-
Notifications
You must be signed in to change notification settings - Fork 995
Cache feature for snapshot database #8702
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
Cache feature for snapshot database #8702
Conversation
Signed-off-by: Karim Taam <karim.t2am@gmail.com>
Signed-off-by: Karim Taam <karim.t2am@gmail.com>
Signed-off-by: garyschulte <garyschulte@gmail.com>
Signed-off-by: Karim Taam <karim.t2am@gmail.com>
Signed-off-by: Karim Taam <karim.t2am@gmail.com>
Signed-off-by: Karim Taam <karim.t2am@gmail.com>
Signed-off-by: Karim Taam <karim.t2am@gmail.com>
d6c92d9 to
ea564b2
Compare
Signed-off-by: Karim Taam <karim.t2am@gmail.com>
Signed-off-by: Karim Taam <karim.t2am@gmail.com>
8447c7a to
231399d
Compare
| hidden = true, | ||
| paramLabel = "<BOOLEAN>", | ||
| description = | ||
| "Enable caching of reads during snapshot access to improve performance (default: ${DEFAULT-VALUE})") |
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.
Can you add here that we shouldn't use it with block processing ?
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.
updated the description feel free to tell me if it's better
| throws RocksDBException { | ||
| final Bytes cacheKey = makeCacheKey(segmentId, key); | ||
| Optional<byte[]> cached = cache.getIfPresent(cacheKey); | ||
| //noinspection OptionalAssignedToNull |
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.
Not sure to understand the comment
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.
it's because I'm checking if optional == null, but it's something we want to do, I will move it at the beginning of the class wuth SuppressWarnings
| final byte[] segmentId, | ||
| final byte[] key, | ||
| final ColumnFamilyHandle handle, | ||
| final Cache<Bytes, Optional<byte[]>> cache) |
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.
Just an idea, maybe it is clear for everyone but I wonder if adding a comment that explains why the value in the cache is an optional, because we want to cache zero reads.
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.
added a comment
Signed-off-by: Karim Taam <karim.t2am@gmail.com>
Signed-off-by: Karim Taam <karim.t2am@gmail.com>
| .getWorldState(withBlockHeaderAndNoUpdateNodeHead(chainHeadBlockHeader)) | ||
| .orElseThrow()) { | ||
| if (worldState instanceof BonsaiWorldState bonsaiWorldState) { | ||
| bonsaiWorldState.disableCacheMerkleTrieLoader(); |
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.
👍
| WorldUpdater updater = getEffectiveWorldStateUpdater(ws); | ||
|
|
||
| if (ws instanceof BonsaiWorldState bonsaiWorldState) { | ||
| bonsaiWorldState.disableCacheMerkleTrieLoader(); |
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.
👍
garyschulte
left a comment
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.
LGTM, I think we would do better to have segment specific caches though so we can leverage different update patterns
| return snapTx.get(segment, key); | ||
| try (final OperationTimer.TimingContext ignored = metrics.getReadLatency().startTimer()) { | ||
| final ColumnFamilyHandle handle = columnFamilyMapper.apply(segment); | ||
| if (isReadCacheEnabledForSnapshots && segment.isEligibleToHighSpecFlag()) { |
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.
requiring high spec would includes blockchain queries (which afaik should only be the corresponding body and header for this snapshot), but omits code. It might make sense to remove this condition entirely, since snapshots should only be used to access rpc-relevant things. the largest values are going to be block bodies, and they are not omitted by this check.
I can see how we might end up with multiple copies of the same code cached for each snapshot. ambivalent about this. it might be better to have a non-snapshot specific code cache, since the code hash key is deterministic.
having column family-specific read caches is probably a better approach in general since there are different update patterns for each. We can make better use of shared caches for several segments like blockchain and code
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.
it might be better to have a non-snapshot specific code cache, since the code hash key is deterministic.
Not sure to understand this comment. I agree with your comment related to blocks but in this case, it is not an issue, block data calls doesn't go through this code as far as know, I could be wrong. The idea was to exclude caching the result of get calls related to code. We don't want to cache it at all here.
|
any reason not to merge this @matkt ? |
|
re-enabling auto-merge after the failed metrics CLI passed locally. I still think we could do smarter caching here though. |
yes we can try to do a more optimized version if we really want to use this feature in mainnet or by default |
PR description
This PR refactors the DB snapshot (thanks to @garyschulte's commit) to remove the use of transactions, as a snapshot is immutable by nature.
Additionally, it introduces an optional cache layer at the snapshot level to optimize repeated reads.
Tests :
Fixed Issue(s)
Thanks for sending a pull request! Have you done the following?
doc-change-requiredlabel to this PR if updates are required.Locally, you can run these tests to catch failures early:
./gradlew spotlessApply./gradlew build./gradlew acceptanceTest./gradlew integrationTest./gradlew ethereum:referenceTests:referenceTests