zeitgeist
zeitgeist copied to clipboard
Research performance cost of duplicate reads and implement a solution if necessary
Storage overlay prevents the worst effects of double reads, but the official suggestion is still to avoid excessive use of this feature: https://substrate.stackexchange.com/questions/2574/clarity-on-storage-read-write-caching.
My suggestion is to use the following design:
type DbReader<K, V> = dyn Fn(K) -> Result<V, Box<dyn std::error::Error>> + Send + Sync;
struct Lazy<K, V> {
key: K,
object: OnceCell<V>,
db_reader: Box<DbReader<K, V>>,
}
impl<K: Copy, V> Lazy<K, V> {
fn new(key: K, db_reader: Box<DbReader<K, V>>) -> Self {
Lazy {
key,
object: OnceCell::new(),
db_reader,
}
}
fn get(&self) -> Result<&V, Box<dyn std::error::Error>> {
self.object.get_or_try_init(|| (self.db_reader)(self.key))
}
}
You can even implement Into<Lazy<MarketId, Market>>
for MarketId
. All helper and do_*
functions should take a wrapped Lazy
object.