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

Use CountedStorageMap instead of StorageValue to manage the Events in frame-system #22

Open
wants to merge 1 commit into
base: subspace-v8
Choose a base branch
from

Conversation

NingLin-P
Copy link
Member

With StorageValue the Events is a single array in the state that keep growing as more extrinsic is executed and more events append to this array, which makes execution and storage root calculation slower and slower as allocation/copying/hashing this array takes more and more time.

Similar to how we handle Pending state in frontier (see polkadot-evm/frontier#1575), this PR use CountedStorageMap to manage the event and so each event will present as a single value in the state.

NOTE: this PR also removes #[pallet::whitelist_storage] for the Events state because it is only supported for StorageValue, so if we re-run the benchmark with this PR the extrinsic will be charged weight for outputting event.

TODO: the Events state is cleared in the initialization of the next block, TBC we may need to add migration to ensure the StorageValue event is properly clear after the runtime upgrade.

Copy link
Member

@teor2345 teor2345 left a comment

Choose a reason for hiding this comment

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

Looks good, I just have some non-blocking questions about how it works.

Do we need a subspace ticket for the runtime migration, to make sure we don’t forget?

/// It could otherwise inflate the PoV size of a block.
///
/// Events have a large in-memory size. Box the events to not go out-of-memory
/// just in case someone still reads them from within the runtime.
#[pallet::storage]
#[pallet::whitelist_storage]
#[pallet::disable_try_decode_storage]
Copy link
Member

Choose a reason for hiding this comment

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

I’m not sure I understand the docs here, they could either mean:

  • we don’t need to migrate due to this attribute, or
  • we need to remove this attribute in order to migrate

https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.disable_try_decode_storage.html

#[pallet::whitelist_storage]
#[pallet::getter(fn event_count)]
pub(super) type EventCount<T: Config> = StorageValue<_, EventIndex, ValueQuery>;
CountedStorageMap<_, Identity, u32, Box<EventRecord<T::RuntimeEvent, T::Hash>>, OptionQuery>;
Copy link
Member

Choose a reason for hiding this comment

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

Should we use the type alias here instead?

Suggested change
CountedStorageMap<_, Identity, u32, Box<EventRecord<T::RuntimeEvent, T::Hash>>, OptionQuery>;
CountedStorageMap<_, Identity, EventIndex, Box<EventRecord<T::RuntimeEvent, T::Hash>>, OptionQuery>;

Copy link
Member

Choose a reason for hiding this comment

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

Please update the comment with map's key as well

@@ -1916,7 +1896,8 @@ impl<T: Config> Pallet<T> {
/// execution else it can have a large impact on the PoV size of a block.
Copy link
Member

Choose a reason for hiding this comment

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

event_no_consensus() (above this comment) can be written to be much more efficient now, probably worth doing in case it impacts performance.

Copy link
Member

@vedhavyas vedhavyas left a comment

Choose a reason for hiding this comment

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

this make sense.
I remember we disussed multiple Vec storages but I only see just Events.
Are you planning to create another PR ?

/// It could otherwise inflate the PoV size of a block.
///
/// Events have a large in-memory size. Box the events to not go out-of-memory
/// just in case someone still reads them from within the runtime.
#[pallet::storage]
#[pallet::whitelist_storage]
Copy link
Member

Choose a reason for hiding this comment

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

is it not possible to whitelist the storage prefix instead ?

Copy link
Member Author

Choose a reason for hiding this comment

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

It is not supported by the upstream. It is possible to implement but is non-trivial.

#[pallet::whitelist_storage]
#[pallet::getter(fn event_count)]
pub(super) type EventCount<T: Config> = StorageValue<_, EventIndex, ValueQuery>;
CountedStorageMap<_, Identity, u32, Box<EventRecord<T::RuntimeEvent, T::Hash>>, OptionQuery>;
Copy link
Member

Choose a reason for hiding this comment

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

Please update the comment with map's key as well

@NingLin-P
Copy link
Member Author

I remember we disussed multiple Vec storages but I only see just Events.
Are you planning to create another PR ?

The other one is IntermediateRoots it doesn't exist anymore in the current storage root solution. Also the size of IntermediateRoots is relatively small compared to Events and Pending and is not hurting performance as test out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants