Caching optimizations (#2505)

This commit is contained in:
Arkadiy Paronyan 2016-10-07 12:10:12 +02:00 committed by Gav Wood
parent 533af43313
commit 7756031d06
3 changed files with 21 additions and 15 deletions

View File

@ -21,7 +21,7 @@ use util::sha3::*;
use bit_set::BitSet; use bit_set::BitSet;
use super::super::instructions; use super::super::instructions;
const CACHE_CODE_ITEMS: usize = 4096; const CACHE_CODE_ITEMS: usize = 65536;
/// GLobal cache for EVM interpreter /// GLobal cache for EVM interpreter
pub struct SharedCache { pub struct SharedCache {

View File

@ -47,14 +47,16 @@ pub type ApplyResult = Result<ApplyOutcome, Error>;
/// Account modification state. Used to check if the account was /// Account modification state. Used to check if the account was
/// Modified in between commits and overall. /// Modified in between commits and overall.
enum AccountState { enum AccountState {
/// Account was never modified in this state object. /// Account was loaded from disk and never modified in this state object.
Clean, CleanFresh,
/// Account was loaded from the global cache and never modified.
CleanCached,
/// Account has been modified and is not committed to the trie yet. /// Account has been modified and is not committed to the trie yet.
/// This is set than any of the account data is changed, including /// This is set if any of the account data is changed, including
/// storage and code. /// storage and code.
Dirty, Dirty,
/// Account was modified and committed to the trie. /// Account was modified and committed to the trie.
Commited, Committed,
} }
#[derive(Debug)] #[derive(Debug)]
@ -105,7 +107,15 @@ impl AccountEntry {
fn new_clean(account: Option<Account>) -> AccountEntry { fn new_clean(account: Option<Account>) -> AccountEntry {
AccountEntry { AccountEntry {
account: account, account: account,
state: AccountState::Clean, state: AccountState::CleanFresh,
}
}
// Create a new account entry and mark it as clean and cached.
fn new_clean_cached(account: Option<Account>) -> AccountEntry {
AccountEntry {
account: account,
state: AccountState::CleanCached,
} }
} }
@ -508,7 +518,7 @@ impl State {
{ {
let mut trie = factories.trie.from_existing(db.as_hashdb_mut(), root).unwrap(); let mut trie = factories.trie.from_existing(db.as_hashdb_mut(), root).unwrap();
for (address, ref mut a) in accounts.iter_mut().filter(|&(_, ref a)| a.is_dirty()) { for (address, ref mut a) in accounts.iter_mut().filter(|&(_, ref a)| a.is_dirty()) {
a.state = AccountState::Commited; a.state = AccountState::Committed;
match a.account { match a.account {
Some(ref mut account) => { Some(ref mut account) => {
try!(trie.insert(address, &account.rlp())); try!(trie.insert(address, &account.rlp()));
@ -526,7 +536,7 @@ impl State {
fn commit_cache(&mut self) { fn commit_cache(&mut self) {
let mut addresses = self.cache.borrow_mut(); let mut addresses = self.cache.borrow_mut();
trace!("Committing cache {:?} entries", addresses.len()); trace!("Committing cache {:?} entries", addresses.len());
for (address, a) in addresses.drain().filter(|&(_, ref a)| !a.is_dirty()) { for (address, a) in addresses.drain().filter(|&(_, ref a)| a.state == AccountState::Committed || a.state == AccountState::CleanFresh) {
self.db.cache_account(address, a.account); self.db.cache_account(address, a.account);
} }
} }
@ -638,10 +648,7 @@ impl State {
Self::update_account_cache(require, account, accountdb.as_hashdb()); Self::update_account_cache(require, account, accountdb.as_hashdb());
} }
let r = f(maybe_acc.as_ref()); let r = f(maybe_acc.as_ref());
match maybe_acc { self.insert_cache(a, AccountEntry::new_clean(maybe_acc));
Some(account) => self.insert_cache(a, AccountEntry::new_clean(Some(account))),
None => self.insert_cache(a, AccountEntry::new_clean(None)),
}
r r
} }
} }
@ -660,8 +667,7 @@ impl State {
let contains_key = self.cache.borrow().contains_key(a); let contains_key = self.cache.borrow().contains_key(a);
if !contains_key { if !contains_key {
match self.db.get_cached_account(a) { match self.db.get_cached_account(a) {
Some(Some(acc)) => self.insert_cache(a, AccountEntry::new_clean(Some(acc))), Some(acc) => self.insert_cache(a, AccountEntry::new_clean_cached(acc)),
Some(None) => self.insert_cache(a, AccountEntry::new_clean(None)),
None => { None => {
let maybe_acc = if self.db.check_account_bloom(a) { let maybe_acc = if self.db.check_account_bloom(a) {
let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR); let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR);

View File

@ -24,7 +24,7 @@ use bloom_journal::{Bloom, BloomJournal};
use db::COL_ACCOUNT_BLOOM; use db::COL_ACCOUNT_BLOOM;
use byteorder::{LittleEndian, ByteOrder}; use byteorder::{LittleEndian, ByteOrder};
const STATE_CACHE_ITEMS: usize = 65536; const STATE_CACHE_ITEMS: usize = 256000;
pub const ACCOUNT_BLOOM_SPACE: usize = 1048576; pub const ACCOUNT_BLOOM_SPACE: usize = 1048576;
pub const DEFAULT_ACCOUNT_PRESET: usize = 1000000; pub const DEFAULT_ACCOUNT_PRESET: usize = 1000000;