-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Add special tag to exclude runtime storage items from benchmarking #12205
Add special tag to exclude runtime storage items from benchmarking #12205
Conversation
I structured it so more could be added later. Right now it will panic saying “Only benchmarking(cached) is supported” or something like that if you try an argument other than cached
… On Sep 8, 2022, at 1:12 AM, Keith Yeung ***@***.***> wrote:
@KiChjang commented on this pull request.
In frame/system/src/lib.rs <#12205 (comment)>:
> #[pallet::unbounded]
pub(super) type Events<T: Config> =
StorageValue<_, Vec<Box<EventRecord<T::Event, T::Hash>>>, ValueQuery>;
/// The number of events in the `Events<T>` list.
#[pallet::storage]
+ #[benchmarking(cached)]
I'm a bit ambivalent about this syntax, benchmarking(cached) seems to indicate that I can put keywords other than cached within the parenthesis. Is that true?
—
Reply to this email directly, view it on GitHub <#12205 (review)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AAOE4LOWQWWBCDVSCVDBPATV5FYTJANCNFSM6AAAAAAQG3H3QA>.
You are receiving this because you were assigned.
|
So my newest problem is I have my macro gen code in let whitelisted_storage_keys_impl = quote::quote![
impl<#type_use_gen> frame_support::traits::WhitelistedStorageKeys for #pallet_ident<#type_use_gen> {
fn whitelisted_storage_keys() -> #frame_support::sp_std::vec::Vec<#frame_support::traits::TrackedStorageKey> {
let info = Pallet::<T>::storage_info();
#frame_support::sp_std::vec::Vec::new()
}
}
]; I'm trying to get an access to
Anyone know how to deal with this and/or know of a better way to read the storage keys from within my impl method? |
Solved using a setup like below. Turns out I was misusing let whitelisted_storage_keys_impl = quote::quote![
use #frame_support::traits::StorageInfoTrait;
impl<#type_impl_gen> #frame_support::traits::WhitelistedStorageKeys for #pallet_ident<#type_use_gen> {
fn whitelisted_storage_keys() -> #frame_support::sp_std::vec::Vec<#frame_support::traits::TrackedStorageKey> {
let info = #pallet_ident::<#type_use_gen>::storage_info();
#frame_support::sp_std::vec::Vec::new()
}
}
]; Hopefully this will let me do something useful with the |
7c0103d
to
f31c859
Compare
* will be used for later expansion
* now based just on key, and available in no-std
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 after fixing my comment
Co-authored-by: Keith Yeung <[email protected]>
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, just some last nitpicks.
Co-authored-by: Bastian Köcher <[email protected]>
bot merge |
…aritytech#12205) * initial setup * add WhitelistedStorageKeys trait * add (A, B) tuple implementation for whitelisted_storage_keys() * fix formatting * implement WhitelistedStorageKeys for all tuple combinations * impl_for_tuples up to 128 for WhitelistedStorageKeys * refactor to #[benchmarking(cached)] * tweak error message and mark BlockNumber as cached * add benchmarking(cached) to the other default types * add docs for benchmarking(cached) * properly parse storage type declaration * make storage_alias structs public so we can use them in this macro * use BTreeMap since TrackedStorageKey missing Ord outside of std * make WhitelistedStorageKeys accessible * basic detection of benchmarking(cached) 💥 * proper parsing of #[benchmarking(cached)] from pallet parse macro * store presence of #[benchmarking(cached)] macro on StorageDef * will be used for later expansion * compiling blank impl for WhitelistedStorageKeys * move impl to expand_pallet_struct * use frame_support::sp_std::vec::Vec properly * successfully compiling with storage info loaded into a variable 💥 * plausible implementation for whitelisted_storage_keys() * depends on the assumption that storage_info.encode() can be loaded into TrackedStorageKey::new(..) * use Pallet::whitelisted_storage_keys() instead of hard-coded list * AllPallets::whitelisted_storage_keys() properly working 💥 * collect storage names * whitelisted_storage_keys() impl working 💥 * clean up * fix compiler error * just one compiler error * fix doc compiler error * use better import path * fix comment * whoops * whoops again * fix macro import issue * cargo fmt * mark example as ignore * use keyword tokens instead of string parsing * fix keyword-based parsing of benchmarking(cached) * preliminary spec for check_whitelist() * add additional test for benchmarking whitelist * add TODO note * remove irrelevant line from example * use filter_map instead of filter and map * simplify syntax Co-authored-by: Keith Yeung <[email protected]> * clean up * fix test * fix tests * use keyword parsing instead of string parsing * use collect() instead of a for loop Co-authored-by: Kian Paimani <[email protected]> * fix compiler error * clean up benchmarking(cached) marking code * use cloned() * refactor to not use panic! and remove need for pub types in storage_alias * remove unneeded use Co-authored-by: Bastian Köcher <[email protected]> * remove unneeded visibility changes * don't manually hard code hash for treasury account as hex * proper Ord, PartialOrd, and Hash impls for TrackedStorageKey * now based just on key, and available in no-std * use BTreeSet instead of BTreeMap * fix comments * cargo fmt * switch to pallet::whitelist and re-do it basti's way :D * make PartialOrd for TrackedStorageKey consistent with Ord * more correct implementation of hash-related traits for TrackedStorageKey * fix integration test * update TODO * remove unused keyword * remove more unused keywords * use into_iter() Co-authored-by: Keith Yeung <[email protected]> * Update frame/support/procedural/src/pallet/parse/mod.rs Co-authored-by: Bastian Köcher <[email protected]> * add docs for whitelisted * fix comment Co-authored-by: Keith Yeung <[email protected]> Co-authored-by: Kian Paimani <[email protected]> Co-authored-by: Bastian Köcher <[email protected]>
Description
The Substrate runtime takes advantage of a storage cache where the first read of a storage item places an item in the cache, and subsequent reads of that item happen in memory.
There are some storage items which we know will be accessed every block, and thus we ignore reads to these items already in our benchmarking: https://github.com/paritytech/substrate/blob/master/bin/node/runtime/src/lib.rs#L1683
This PR adds a
#[pallet::whitelist_storage]
attribute macro that can be applied to storage item declarations. Doing so will result in that storage item's storage key being automatically added to the whitelist shown above, meaning they will be excluded from benchmarking calculations. The PR also replaces the existing hard-coded whitelist with#[pallet::whitelist_storage]
calls that will instead generate the list organically.This is accomplished by aggregating the
#[pallet::whitelist_storage]
attribute flags during pallet macro generation time, reading the storage keys for each storage item, and auto-implementing the traitWhitelistedStorageKeys
which adds a function to each implementing pallet returning aVec<TrackedStorageKey>
listing the storage keys within that pallet that have been marked. This vec is then used in place of the hard-coded whitelist shown above.Note that the actual attribute macro does nothing other than verify that it has been attached to a storage item declaration. The actual meat of this functionality all occurs in the pallet macro generation code.
A moonshot goal here that we may or may not be able to accomplish in this PR would be to panic if we can statically detect that the storage item the macro is being attached to is never read (or, even harder to detect, if it is infrequently read). This would prevent situations where the macro is applied to something it shouldn't be. That functionality probably won't be in scope for this PR, but noting here.
Notes
#[benchmarking(cached)]
Follow-up Work
#[pallet::
attribute macros are currently parsed and have their tokens entirely removed by the main pallet proc macro. As a result there is actually no attribute macro definition for the individual variants ofpallet::
, making it very hard to find docs or look up these macros in docs.rs, etc. In the future we should add blank macro stubs for all thepallet::
macros that lack stubs and attach their documentation to these stubs instead of burying it in theframe_support
main doc page. This could be a future PR.#[pallet::cache_storage]
which will result in the storage key automatically being read at the beginning of every block. This will also automatically whitelist the storage.Related Issues