-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2a50a99
commit ae91f49
Showing
8 changed files
with
260 additions
and
98 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
use std::collections::BTreeSet; | ||
use std::sync::atomic::AtomicBool; | ||
use std::sync::atomic::AtomicU64; | ||
use std::sync::atomic::Ordering; | ||
|
||
use dashmap::DashMap; | ||
use parking_lot::RwLock; | ||
use rustc_hash::FxBuildHasher; | ||
|
||
use super::AccountWithSlots; | ||
use crate::eth::primitives::Account; | ||
use crate::eth::primitives::Address; | ||
use crate::eth::primitives::ExecutionChanges; | ||
use crate::eth::primitives::Slot; | ||
use crate::eth::primitives::SlotIndex; | ||
use crate::eth::primitives::SlotValue; | ||
|
||
type EntryId = u64; | ||
|
||
const SLOT_CACHE_LIMIT: usize = 10_000; | ||
|
||
pub struct StorageCache { | ||
entry_id: AtomicU64, | ||
should_check_eviction: AtomicBool, | ||
cached_slots: DashMap<(SlotIndex, Address), (SlotValue, EntryId), FxBuildHasher>, | ||
slot_eviction_queue: RwLock<BTreeSet<(EntryId, SlotIndex, Address)>>, | ||
cached_accounts: DashMap<Address, (Account, EntryId), FxBuildHasher>, | ||
} | ||
|
||
impl StorageCache { | ||
pub fn new() -> StorageCache { | ||
StorageCache { | ||
entry_id: AtomicU64::new(0), | ||
should_check_eviction: AtomicBool::new(false), | ||
cached_slots: DashMap::default(), | ||
cached_accounts: DashMap::default(), | ||
slot_eviction_queue: RwLock::new(BTreeSet::new()), | ||
} | ||
} | ||
|
||
pub fn cache_slot(&self, address: Address, slot: Slot) { | ||
self.cached_slots.insert((slot.index, address), (slot.value, self.next_id())); | ||
} | ||
|
||
pub fn cache_account(&self, account: Account) { | ||
self.cached_accounts.insert(account.address, (account, self.next_id())); | ||
} | ||
|
||
pub fn cache_account_and_slots_from_execution(&self, changes: &ExecutionChanges) { | ||
for change in changes.values() { | ||
// cache slots | ||
let mut slots = vec![]; | ||
for &slot in change.slots.values().flat_map(|slot| slot.take_ref()) { | ||
slots.push(slot); | ||
} | ||
|
||
for slot in slots { | ||
self.cached_slots.insert((slot.index, change.address), (slot.value, self.next_id())); | ||
// self.slot_eviction_queue | ||
} | ||
|
||
// cache account | ||
let mut account = AccountWithSlots::new(change.address); | ||
if let Some(nonce) = change.nonce.take_ref() { | ||
account.info.nonce = *nonce; | ||
} | ||
if let Some(balance) = change.balance.take_ref() { | ||
account.info.balance = *balance; | ||
} | ||
if let Some(Some(bytecode)) = change.bytecode.take_ref() { | ||
account.info.bytecode = Some(bytecode.clone()); | ||
} | ||
|
||
self.cached_accounts.insert(account.info.address, (account.info, self.next_id())); | ||
} | ||
|
||
self.evict_if_necessary(); | ||
} | ||
|
||
pub fn get_slot(&self, address: Address, index: SlotIndex) -> Option<Slot> { | ||
self.cached_slots.get(&(index, address)).map(|pair| Slot { value: pair.value().0, index }) | ||
} | ||
|
||
pub fn get_account(&self, address: Address) -> Option<Account> { | ||
self.cached_accounts.get(&address).map(|pair| pair.value().0.clone()) | ||
} | ||
|
||
/// Clears space if capacity was surpassed. | ||
fn evict_if_necessary(&self) { | ||
// if !self.should_check_eviction.fetch_and(false, Ordering::Relaxed) { | ||
// return; | ||
// } | ||
|
||
// let mut slot_count = self.cached_slots.len(); | ||
// while slot_count > SLOT_CACHE_LIMIT { | ||
// // Unwrap safety: | ||
// // eviction queue should have same size as cached_slots | ||
// let (_id, index, value) = self.slot_eviction_queue.write().pop_first().unwrap(); | ||
|
||
// self.cached_slots.remove(&(index, value)); | ||
|
||
// slot_count -= 1; | ||
// } | ||
} | ||
|
||
fn next_id(&self) -> EntryId { | ||
let id = self.entry_id.fetch_add(1, Ordering::Relaxed); | ||
if id % 8192 == 0 { | ||
self.should_check_eviction.store(true, Ordering::Relaxed); | ||
} | ||
id | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.