Skip to content
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

RPC cache system #1083

Draft
wants to merge 17 commits into
base: main
Choose a base branch
from

Conversation

tchataigner
Copy link

Pull Request type

Please add the labels corresponding to the type of changes your PR introduces:

  • Feature

What is the current behavior?

In the current implementation of the madara client, we fetch block data by going through the generated logs of our pallet. As the block data is important and we need fast retrieval, it seems important to:

  • Properly store the block data in a dedicated StorageValue in our pallet
  • When possible retrieve the block data through storage query instead of digest API
  • Add a cache layer on top of it to ease retrieval of recurrent queried data

Resolves: #947

What is the new behavior?

Right now, the update to the code base are as follow:

  • Added a CurrentBlock type in the starknet pallet, representing a StorageValue containing our block data. Also added a getter to retrieve it through our runtime API.
  • Added necessary method over our storage implementation to both retrieve the data through the runtime API and directly from our storage.
  • Implemented a base LRUCache limited by allocated memory, along with an asynchronous task responsible for the handling of the cache and retrieving data.
  • Updated the necessary calls in our RPC implementation, to use the cache task instead of directly retrieving the block data through our logs.
  • Added an argument over the run command to set the allocated memory size limit for the cache.

The new flow is:

  1. Run a madara run while specifying --starknet-log-block-cache-size. For now, the default value is 200 (most likely will cache little if not nothing)
  2. On RPC call, we will send the requested block hash to our data cache task.
  3. If the data cache has the block, returns it.
  4. Otherwise, we will directly query our storage for it.

Does this introduce a breaking change?

No

Other information

Original issue: #947

This commit introduces a base LRU cache that will be used for the RPC layer. It is inspired by frontier's code base:
https://github.com/paritytech/frontier/blob/194f6bb06152402ba44b340c3d401ae6e0670d96/client/rpc/src/eth/cache/mod.rs#L76

Extending it, our approach proposes two types of limiter:
- Values size limiter: A limiter that will base its cache management on the total size of all values stored in the cache
- Allocated size limiter: A limiter that will base its cache management on the allocated memory for the cache

This allows for either an approximate or a precise memory management, which could prove useful in our P2P context.
We added a StorageValue for blocks in the pallet_starknet, allowing us to retrieve block data through storage.
We chose to keep memory management by allocated memory as this allows for a more precise control.
@codecov
Copy link

codecov bot commented Sep 11, 2023

Codecov Report

Patch coverage: 15.93% and project coverage change: -0.35% ⚠️

Comparison is base (a6f6554) 40.71% compared to head (b63d1a8) 40.36%.
Report is 1 commits behind head on main.

❗ Current head b63d1a8 differs from pull request most recent head 59b7c99. Consider uploading reports for the commit 59b7c99 to get more accurate results

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1083      +/-   ##
==========================================
- Coverage   40.71%   40.36%   -0.35%     
==========================================
  Files          96       98       +2     
  Lines       11069    11281     +212     
  Branches    11069    11281     +212     
==========================================
+ Hits         4507     4554      +47     
- Misses       6050     6209     +159     
- Partials      512      518       +6     
Files Changed Coverage Δ
crates/client/rpc-core/src/lib.rs 0.00% <ø> (ø)
crates/client/rpc/src/cache/mod.rs 0.00% <0.00%> (ø)
crates/client/rpc/src/events/mod.rs 22.22% <0.00%> (-0.20%) ⬇️
crates/client/rpc/src/lib.rs 0.00% <0.00%> (ø)
crates/client/rpc/src/madara_backend_client.rs 0.00% <ø> (ø)
crates/client/storage/src/lib.rs 0.00% <ø> (ø)
crates/client/storage/src/overrides/mod.rs 0.00% <0.00%> (ø)
...client/storage/src/overrides/schema_v1_override.rs 0.00% <0.00%> (ø)
crates/node/src/cli.rs 0.00% <0.00%> (ø)
crates/node/src/command.rs 0.00% <0.00%> (ø)
... and 7 more

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@tchataigner
Copy link
Author

tchataigner commented Sep 11, 2023

Hey @tdelabro, here is a first draft for the RPC cache.

As we discussed under the issue, I've implemented the cache to work with allocated memory size instead of values size to make it more precise.

Right now, it seems to fail integration test, which is strange as it passes on my computer. I'll look into it.

The only problem that I have is that I think the benchmark tests to evaluate the cache efficiency are not there. I wanted to add some to try and measure it but I'm having trouble in identifying how to pull that off.

Could I ask for your input on that ? Ideally, I think that we want to try and spam a request on loop to our RPC methods that concern block fetch (e.g.: getblockWithTxHashes)

Also, I'd be interested in your opinion of the choice I made to implement a new StorageValue in pallet-starknet. Does it seem like a fair choice to you?

@tchataigner tchataigner changed the title RPC cache RPC cache system Sep 11, 2023
Copy link
Collaborator

@EvolveArt EvolveArt left a comment

Choose a reason for hiding this comment

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

left few comments

crates/client/rpc/src/cache/lru_cache.rs Outdated Show resolved Hide resolved
crates/client/rpc/src/cache/lru_cache.rs Outdated Show resolved Hide resolved
}

#[cfg(test)]
mod tests {
Copy link
Collaborator

Choose a reason for hiding this comment

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

is there a way we can add tests for the metrics too?

/// Represent a pair of a cache and a data waitlist, used to communicate information between our
/// internal methods.
struct CacheWaitlist<B: BlockT, T> {
cache: LRUCache<<B as BlockT>::Hash, T>,
Copy link
Collaborator

Choose a reason for hiding this comment

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

not sure we need to use this hasher here tho, we should probably optimize for performance here w/ blake2

}

/// Cache for `get_block_by_block_hash`.
pub async fn get_block_by_block_hash(
Copy link
Collaborator

Choose a reason for hiding this comment

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

wdyt about adding one for tx status like its done in frontier ? With 0.12.1 this now makes total sense

get_block_by_block_hash(self.client.as_ref(), substrate_block_hash).unwrap_or_default();
let schema = mc_storage::onchain_storage_schema(self.client.as_ref(), substrate_block_hash);

let block = self.data_cache.get_block_by_block_hash(schema, substrate_block_hash).await.unwrap_or_default();
Copy link
Collaborator

Choose a reason for hiding this comment

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

let's refractor this code

let schema = mc_storage::onchain_storage_schema(self.client.as_ref(), substrate_block_hash);

        let block = self.data_cache.get_block_by_block_hash(schema, substrate_block_hash).await.unwrap_or_default();

to smth like let block = self.get_block_from_cache(substrate_block_hash)

tchataigner and others added 2 commits September 12, 2023 17:32
Co-authored-by: 0xevolve <Artevolve@yahoo.com>
Co-authored-by: 0xevolve <Artevolve@yahoo.com>
@github-actions
Copy link

There hasn't been any activity on this pull request recently, and in order to prioritize active work, it has been marked as stale.
This PR will be closed and locked in 7 days if no further activity occurs.
Thank you for your contributions!

@github-actions github-actions bot added the stale label Oct 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

dev: add LRU cache layer to block fetching client-side
2 participants