pub struct StoragePagedList<Prefix, Value, ValuesPerNewPage> { /* private fields */ }
Expand description

A paginated storage list.

Motivation

This type replaces StorageValue<Vec<V>> in situations where only iteration and appending is needed. There are a few places where this is the case. A paginated structure reduces the memory usage when a storage transactions needs to be rolled back. The main motivation is therefore a reduction of runtime memory on storage transaction rollback. Should be configured such that the size of a page is about 64KiB. This can only be ensured when V implements MaxEncodedLen.

Implementation

The metadata of this struct is stored in [StoragePagedListMeta]. The data is stored in [Page]s.

Each [Page] holds at most ValuesPerNewPage values in its values vector. The last page is the only one that could have less than ValuesPerNewPage values.
Iteration happens by starting at [first_page][StoragePagedListMeta::first_page]/ [first_value_offset][StoragePagedListMeta::first_value_offset] and incrementing these indices as long as there are elements in the page and there are pages in storage. All elements of a page are loaded once a page is read from storage. Iteration then happens on the cached elements. This reduces the number of storage read calls on the overlay. Appending to the list happens by appending to the last page by utilizing sp_io::storage::append. It allows to directly extend the elements of values vector of the page without loading the whole vector from storage. A new page is instantiated once [Page::next] overflows ValuesPerNewPage. Its vector will also be created through sp_io::storage::append. Draining advances the internal indices identical to Iteration. It additionally persists the increments to storage and thereby ‘drains’ elements. Completely drained pages are deleted from storage.

Further Observations

  • The encoded layout of a page is exactly its [Page::values]. The [Page::next] offset is stored in the [StoragePagedListMeta] instead. There is no particular reason for this, besides having all management state handy in one location.
  • The PoV complexity of iterating compared to a StorageValue<Vec<V>> is improved for “shortish” iterations and worse for total iteration. The append complexity is identical in the asymptotic case when using an Appender, and worse in all. For example when appending just one value.
  • It does incur a read overhead on the host side as compared to a StorageValue<Vec<V>>.

Trait Implementations§

source§

impl<Prefix, Value, ValuesPerNewPage> StorageList<Value> for StoragePagedList<Prefix, Value, ValuesPerNewPage>where Prefix: StorageInstance, Value: FullCodec, ValuesPerNewPage: Get<u32>,

§

type Iterator = StoragePagedListIterator<Prefix, Value, ValuesPerNewPage>

Iterator for normal and draining iteration.
§

type Appender = StoragePagedListMeta<Prefix, Value, ValuesPerNewPage>

Append iterator for fast append operations.
source§

fn iter() -> Self::Iterator

List the elements in append order.
source§

fn drain() -> Self::Iterator

Drain the elements in append order. Read more
source§

fn appender() -> Self::Appender

A fast append iterator.
source§

fn append_one<EncodeLikeValue>(item: EncodeLikeValue)where EncodeLikeValue: EncodeLike<V>,

Append a single element. Read more
source§

fn append_many<EncodeLikeValue, I>(items: I)where EncodeLikeValue: EncodeLike<V>, I: IntoIterator<Item = EncodeLikeValue>,

Append many elements. Read more
source§

impl<Prefix, Value, ValuesPerNewPage> StoragePrefixedContainer for StoragePagedList<Prefix, Value, ValuesPerNewPage>where Prefix: StorageInstance, Value: FullCodec, ValuesPerNewPage: Get<u32>,

source§

fn module_prefix() -> &'static [u8]

Module prefix. Used for generating final key.
source§

fn storage_prefix() -> &'static [u8]

Storage prefix. Used for generating final key.
source§

fn final_prefix() -> [u8; 32]

Final full prefix that prefixes all keys.

Auto Trait Implementations§

§

impl<Prefix, Value, ValuesPerNewPage> RefUnwindSafe for StoragePagedList<Prefix, Value, ValuesPerNewPage>where Prefix: RefUnwindSafe, Value: RefUnwindSafe, ValuesPerNewPage: RefUnwindSafe,

§

impl<Prefix, Value, ValuesPerNewPage> Send for StoragePagedList<Prefix, Value, ValuesPerNewPage>where Prefix: Send, Value: Send, ValuesPerNewPage: Send,

§

impl<Prefix, Value, ValuesPerNewPage> Sync for StoragePagedList<Prefix, Value, ValuesPerNewPage>where Prefix: Sync, Value: Sync, ValuesPerNewPage: Sync,

§

impl<Prefix, Value, ValuesPerNewPage> Unpin for StoragePagedList<Prefix, Value, ValuesPerNewPage>where Prefix: Unpin, Value: Unpin, ValuesPerNewPage: Unpin,

§

impl<Prefix, Value, ValuesPerNewPage> UnwindSafe for StoragePagedList<Prefix, Value, ValuesPerNewPage>where Prefix: UnwindSafe, Value: UnwindSafe, ValuesPerNewPage: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CheckedConversion for T

source§

fn checked_from<T>(t: T) -> Option<Self>where Self: TryFrom<T>,

Convert from a value of T into an equivalent instance of Option<Self>. Read more
source§

fn checked_into<T>(self) -> Option<T>where Self: TryInto<T>,

Consume self to return Some equivalent value of Option<T>. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IsType<T> for T

source§

fn from_ref(t: &T) -> &T

Cast reference.
source§

fn into_ref(&self) -> &T

Cast reference.
source§

fn from_mut(t: &mut T) -> &mut T

Cast mutable reference.
source§

fn into_mut(&mut self) -> &mut T

Cast mutable reference.
source§

impl<T, Outer> IsWrappedBy<Outer> for Twhere Outer: AsRef<T> + AsMut<T> + From<T>, T: From<Outer>,

source§

fn from_ref(outer: &Outer) -> &T

Get a reference to the inner from the outer.

source§

fn from_mut(outer: &mut Outer) -> &mut T

Get a mutable reference to the inner from the outer.

§

impl<T> Pointable for T

§

const ALIGN: usize = mem::align_of::<T>()

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> SaturatedConversion for T

source§

fn saturated_from<T>(t: T) -> Selfwhere Self: UniqueSaturatedFrom<T>,

Convert from a value of T into an equivalent instance of Self. Read more
source§

fn saturated_into<T>(self) -> Twhere Self: UniqueSaturatedInto<T>,

Consume self to return an equivalent value of T. Read more
source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<S, T> UncheckedInto<T> for Swhere T: UncheckedFrom<S>,

source§

fn unchecked_into(self) -> T

The counterpart to unchecked_from.
source§

impl<T, S> UniqueSaturatedInto<T> for Swhere T: Bounded, S: TryInto<T>,

source§

fn unique_saturated_into(self) -> T

Consume self to return an equivalent value of T.
§

impl<V, T> VZip<V> for Twhere V: MultiLane<T>,

§

fn vzip(self) -> V

source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
§

impl<T> JsonSchemaMaybe for T

source§

impl<T> MaybeRefUnwindSafe for Twhere T: RefUnwindSafe,