Performance optimizations (#1642)
* Optimize ethash verification * disable WAL for puts * Clear account cache after commit * Commit only modified accounts * Optimize existing block check * Cache last hashes
This commit is contained in:
parent
5dba43178b
commit
5ab18d1313
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -1078,7 +1078,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "rocksdb"
|
name = "rocksdb"
|
||||||
version = "0.4.5"
|
version = "0.4.5"
|
||||||
source = "git+https://github.com/ethcore/rust-rocksdb#6472a9dce16c267a3acec2ee6fd01d1bf8de4913"
|
source = "git+https://github.com/ethcore/rust-rocksdb#dd597245bfcb621c6ffc45478e1fda0b05d2f409"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rocksdb-sys 0.3.0 (git+https://github.com/ethcore/rust-rocksdb)",
|
"rocksdb-sys 0.3.0 (git+https://github.com/ethcore/rust-rocksdb)",
|
||||||
@ -1087,7 +1087,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "rocksdb-sys"
|
name = "rocksdb-sys"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/ethcore/rust-rocksdb#6472a9dce16c267a3acec2ee6fd01d1bf8de4913"
|
source = "git+https://github.com/ethcore/rust-rocksdb#dd597245bfcb621c6ffc45478e1fda0b05d2f409"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -271,11 +271,12 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64)
|
|||||||
|
|
||||||
let page_size = 4 * MIX_WORDS;
|
let page_size = 4 * MIX_WORDS;
|
||||||
let num_full_pages = (full_size / page_size) as u32;
|
let num_full_pages = (full_size / page_size) as u32;
|
||||||
|
let cache: &[Node] = &light.cache; // deref once for better performance
|
||||||
|
|
||||||
for i in 0..(ETHASH_ACCESSES as u32) {
|
for i in 0..(ETHASH_ACCESSES as u32) {
|
||||||
let index = fnv_hash(f_mix.get_unchecked(0).as_words().get_unchecked(0) ^ i, *mix.get_unchecked(0).as_words().get_unchecked((i as usize) % MIX_WORDS)) % num_full_pages;
|
let index = fnv_hash(f_mix.get_unchecked(0).as_words().get_unchecked(0) ^ i, *mix.get_unchecked(0).as_words().get_unchecked((i as usize) % MIX_WORDS)) % num_full_pages;
|
||||||
for n in 0..MIX_NODES {
|
for n in 0..MIX_NODES {
|
||||||
let tmp_node = calculate_dag_item(index * MIX_NODES as u32 + n as u32, light);
|
let tmp_node = calculate_dag_item(index * MIX_NODES as u32 + n as u32, cache);
|
||||||
for w in 0..NODE_WORDS {
|
for w in 0..NODE_WORDS {
|
||||||
*mix.get_unchecked_mut(n).as_words_mut().get_unchecked_mut(w) = fnv_hash(*mix.get_unchecked(n).as_words().get_unchecked(w), *tmp_node.as_words().get_unchecked(w));
|
*mix.get_unchecked_mut(n).as_words_mut().get_unchecked_mut(w) = fnv_hash(*mix.get_unchecked(n).as_words().get_unchecked(w), *tmp_node.as_words().get_unchecked(w));
|
||||||
}
|
}
|
||||||
@ -306,18 +307,17 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_dag_item(node_index: u32, light: &Light) -> Node {
|
fn calculate_dag_item(node_index: u32, cache: &[Node]) -> Node {
|
||||||
unsafe {
|
unsafe {
|
||||||
let num_parent_nodes = light.cache.len();
|
let num_parent_nodes = cache.len();
|
||||||
let cache_nodes = &light.cache;
|
let init = cache.get_unchecked(node_index as usize % num_parent_nodes);
|
||||||
let init = cache_nodes.get_unchecked(node_index as usize % num_parent_nodes);
|
|
||||||
let mut ret = init.clone();
|
let mut ret = init.clone();
|
||||||
*ret.as_words_mut().get_unchecked_mut(0) ^= node_index;
|
*ret.as_words_mut().get_unchecked_mut(0) ^= node_index;
|
||||||
sha3::sha3_512(ret.bytes.as_mut_ptr(), ret.bytes.len(), ret.bytes.as_ptr(), ret.bytes.len());
|
sha3::sha3_512(ret.bytes.as_mut_ptr(), ret.bytes.len(), ret.bytes.as_ptr(), ret.bytes.len());
|
||||||
|
|
||||||
for i in 0..ETHASH_DATASET_PARENTS {
|
for i in 0..ETHASH_DATASET_PARENTS {
|
||||||
let parent_index = fnv_hash(node_index ^ i, *ret.as_words().get_unchecked(i as usize % NODE_WORDS)) % num_parent_nodes as u32;
|
let parent_index = fnv_hash(node_index ^ i, *ret.as_words().get_unchecked(i as usize % NODE_WORDS)) % num_parent_nodes as u32;
|
||||||
let parent = cache_nodes.get_unchecked(parent_index as usize);
|
let parent = cache.get_unchecked(parent_index as usize);
|
||||||
for w in 0..NODE_WORDS {
|
for w in 0..NODE_WORDS {
|
||||||
*ret.as_words_mut().get_unchecked_mut(w) = fnv_hash(*ret.as_words().get_unchecked(w), *parent.as_words().get_unchecked(w));
|
*ret.as_words_mut().get_unchecked_mut(w) = fnv_hash(*ret.as_words().get_unchecked(w), *parent.as_words().get_unchecked(w));
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,8 @@ pub struct Account {
|
|||||||
code_hash: Option<H256>,
|
code_hash: Option<H256>,
|
||||||
// Code cache of the account.
|
// Code cache of the account.
|
||||||
code_cache: Bytes,
|
code_cache: Bytes,
|
||||||
|
// Account is new or has been modified
|
||||||
|
dirty: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Account {
|
impl Account {
|
||||||
@ -47,7 +49,8 @@ impl Account {
|
|||||||
storage_root: SHA3_NULL_RLP,
|
storage_root: SHA3_NULL_RLP,
|
||||||
storage_overlay: RefCell::new(storage.into_iter().map(|(k, v)| (k, (Filth::Dirty, v))).collect()),
|
storage_overlay: RefCell::new(storage.into_iter().map(|(k, v)| (k, (Filth::Dirty, v))).collect()),
|
||||||
code_hash: Some(code.sha3()),
|
code_hash: Some(code.sha3()),
|
||||||
code_cache: code
|
code_cache: code,
|
||||||
|
dirty: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +62,8 @@ impl Account {
|
|||||||
storage_root: SHA3_NULL_RLP,
|
storage_root: SHA3_NULL_RLP,
|
||||||
storage_overlay: RefCell::new(pod.storage.into_iter().map(|(k, v)| (k, (Filth::Dirty, v))).collect()),
|
storage_overlay: RefCell::new(pod.storage.into_iter().map(|(k, v)| (k, (Filth::Dirty, v))).collect()),
|
||||||
code_hash: Some(pod.code.sha3()),
|
code_hash: Some(pod.code.sha3()),
|
||||||
code_cache: pod.code
|
code_cache: pod.code,
|
||||||
|
dirty: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,6 +76,7 @@ impl Account {
|
|||||||
storage_overlay: RefCell::new(HashMap::new()),
|
storage_overlay: RefCell::new(HashMap::new()),
|
||||||
code_hash: Some(SHA3_EMPTY),
|
code_hash: Some(SHA3_EMPTY),
|
||||||
code_cache: vec![],
|
code_cache: vec![],
|
||||||
|
dirty: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,6 +90,7 @@ impl Account {
|
|||||||
storage_overlay: RefCell::new(HashMap::new()),
|
storage_overlay: RefCell::new(HashMap::new()),
|
||||||
code_hash: Some(r.val_at(3)),
|
code_hash: Some(r.val_at(3)),
|
||||||
code_cache: vec![],
|
code_cache: vec![],
|
||||||
|
dirty: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,6 +104,7 @@ impl Account {
|
|||||||
storage_overlay: RefCell::new(HashMap::new()),
|
storage_overlay: RefCell::new(HashMap::new()),
|
||||||
code_hash: None,
|
code_hash: None,
|
||||||
code_cache: vec![],
|
code_cache: vec![],
|
||||||
|
dirty: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,6 +113,7 @@ impl Account {
|
|||||||
pub fn init_code(&mut self, code: Bytes) {
|
pub fn init_code(&mut self, code: Bytes) {
|
||||||
assert!(self.code_hash.is_none());
|
assert!(self.code_hash.is_none());
|
||||||
self.code_cache = code;
|
self.code_cache = code;
|
||||||
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reset this account's code to the given code.
|
/// Reset this account's code to the given code.
|
||||||
@ -117,6 +125,7 @@ impl Account {
|
|||||||
/// Set (and cache) the contents of the trie's storage at `key` to `value`.
|
/// Set (and cache) the contents of the trie's storage at `key` to `value`.
|
||||||
pub fn set_storage(&mut self, key: H256, value: H256) {
|
pub fn set_storage(&mut self, key: H256, value: H256) {
|
||||||
self.storage_overlay.borrow_mut().insert(key, (Filth::Dirty, value));
|
self.storage_overlay.borrow_mut().insert(key, (Filth::Dirty, value));
|
||||||
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get (and cache) the contents of the trie's storage at `key`.
|
/// Get (and cache) the contents of the trie's storage at `key`.
|
||||||
@ -172,6 +181,10 @@ impl Account {
|
|||||||
!self.code_cache.is_empty() || (self.code_cache.is_empty() && self.code_hash == Some(SHA3_EMPTY))
|
!self.code_cache.is_empty() || (self.code_cache.is_empty() && self.code_hash == Some(SHA3_EMPTY))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Is this a new or modified account?
|
||||||
|
pub fn is_dirty(&self) -> bool {
|
||||||
|
self.dirty
|
||||||
|
}
|
||||||
/// Provide a database to get `code_hash`. Should not be called if it is a contract without code.
|
/// Provide a database to get `code_hash`. Should not be called if it is a contract without code.
|
||||||
pub fn cache_code(&mut self, db: &AccountDB) -> bool {
|
pub fn cache_code(&mut self, db: &AccountDB) -> bool {
|
||||||
// TODO: fill out self.code_cache;
|
// TODO: fill out self.code_cache;
|
||||||
@ -201,16 +214,23 @@ impl Account {
|
|||||||
pub fn storage_overlay(&self) -> Ref<HashMap<H256, (Filth, H256)>> { self.storage_overlay.borrow() }
|
pub fn storage_overlay(&self) -> Ref<HashMap<H256, (Filth, H256)>> { self.storage_overlay.borrow() }
|
||||||
|
|
||||||
/// Increment the nonce of the account by one.
|
/// Increment the nonce of the account by one.
|
||||||
pub fn inc_nonce(&mut self) { self.nonce = self.nonce + U256::from(1u8); }
|
pub fn inc_nonce(&mut self) {
|
||||||
|
self.nonce = self.nonce + U256::from(1u8);
|
||||||
|
self.dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
/// Increment the nonce of the account by one.
|
/// Increment the nonce of the account by one.
|
||||||
pub fn add_balance(&mut self, x: &U256) { self.balance = self.balance + *x; }
|
pub fn add_balance(&mut self, x: &U256) {
|
||||||
|
self.balance = self.balance + *x;
|
||||||
|
self.dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
/// Increment the nonce of the account by one.
|
/// Increment the nonce of the account by one.
|
||||||
/// Panics if balance is less than `x`
|
/// Panics if balance is less than `x`
|
||||||
pub fn sub_balance(&mut self, x: &U256) {
|
pub fn sub_balance(&mut self, x: &U256) {
|
||||||
assert!(self.balance >= *x);
|
assert!(self.balance >= *x);
|
||||||
self.balance = self.balance - *x;
|
self.balance = self.balance - *x;
|
||||||
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Commit the `storage_overlay` to the backing DB and update `storage_root`.
|
/// Commit the `storage_overlay` to the backing DB and update `storage_root`.
|
||||||
|
@ -359,6 +359,12 @@ impl BlockChain {
|
|||||||
bc
|
bc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the given parent block has given child
|
||||||
|
/// (though not necessarily a part of the canon chain).
|
||||||
|
fn is_known_child(&self, parent: &H256, hash: &H256) -> bool {
|
||||||
|
self.extras_db.read_with_cache(&self.block_details, parent).map_or(false, |d| d.children.contains(hash))
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the cache configuration.
|
/// Set the cache configuration.
|
||||||
pub fn configure_cache(&self, pref_cache_size: usize, max_cache_size: usize) {
|
pub fn configure_cache(&self, pref_cache_size: usize, max_cache_size: usize) {
|
||||||
self.pref_cache_size.store(pref_cache_size, AtomicOrder::Relaxed);
|
self.pref_cache_size.store(pref_cache_size, AtomicOrder::Relaxed);
|
||||||
@ -463,7 +469,7 @@ impl BlockChain {
|
|||||||
let header = block.header_view();
|
let header = block.header_view();
|
||||||
let hash = header.sha3();
|
let hash = header.sha3();
|
||||||
|
|
||||||
if self.is_known(&hash) {
|
if self.is_known_child(&header.parent_hash(), &hash) {
|
||||||
return ImportRoute::none();
|
return ImportRoute::none();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,6 +145,7 @@ pub struct Client {
|
|||||||
notify: RwLock<Option<Weak<ChainNotify>>>,
|
notify: RwLock<Option<Weak<ChainNotify>>>,
|
||||||
queue_transactions: AtomicUsize,
|
queue_transactions: AtomicUsize,
|
||||||
previous_enode: Mutex<Option<String>>,
|
previous_enode: Mutex<Option<String>>,
|
||||||
|
last_hashes: RwLock<VecDeque<H256>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const HISTORY: u64 = 1200;
|
const HISTORY: u64 = 1200;
|
||||||
@ -232,6 +233,7 @@ impl Client {
|
|||||||
notify: RwLock::new(None),
|
notify: RwLock::new(None),
|
||||||
queue_transactions: AtomicUsize::new(0),
|
queue_transactions: AtomicUsize::new(0),
|
||||||
previous_enode: Mutex::new(None),
|
previous_enode: Mutex::new(None),
|
||||||
|
last_hashes: RwLock::new(VecDeque::new()),
|
||||||
};
|
};
|
||||||
Ok(Arc::new(client))
|
Ok(Arc::new(client))
|
||||||
}
|
}
|
||||||
@ -253,6 +255,14 @@ impl Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn build_last_hashes(&self, parent_hash: H256) -> LastHashes {
|
fn build_last_hashes(&self, parent_hash: H256) -> LastHashes {
|
||||||
|
{
|
||||||
|
let hashes = self.last_hashes.read();
|
||||||
|
if hashes.front().map_or(false, |h| h == &parent_hash) {
|
||||||
|
let mut res = Vec::from(hashes.clone());
|
||||||
|
res.resize(256, H256::default());
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
let mut last_hashes = LastHashes::new();
|
let mut last_hashes = LastHashes::new();
|
||||||
last_hashes.resize(256, H256::new());
|
last_hashes.resize(256, H256::new());
|
||||||
last_hashes[0] = parent_hash;
|
last_hashes[0] = parent_hash;
|
||||||
@ -264,6 +274,8 @@ impl Client {
|
|||||||
None => break,
|
None => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let mut cached_hashes = self.last_hashes.write();
|
||||||
|
*cached_hashes = VecDeque::from(last_hashes.clone());
|
||||||
last_hashes
|
last_hashes
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -418,6 +430,7 @@ impl Client {
|
|||||||
|
|
||||||
fn commit_block<B>(&self, block: B, hash: &H256, block_data: &[u8]) -> ImportRoute where B: IsBlock + Drain {
|
fn commit_block<B>(&self, block: B, hash: &H256, block_data: &[u8]) -> ImportRoute where B: IsBlock + Drain {
|
||||||
let number = block.header().number();
|
let number = block.header().number();
|
||||||
|
let parent = block.header().parent_hash().clone();
|
||||||
// Are we committing an era?
|
// Are we committing an era?
|
||||||
let ancient = if number >= HISTORY {
|
let ancient = if number >= HISTORY {
|
||||||
let n = number - HISTORY;
|
let n = number - HISTORY;
|
||||||
@ -445,9 +458,20 @@ impl Client {
|
|||||||
enacted: route.enacted.clone(),
|
enacted: route.enacted.clone(),
|
||||||
retracted: route.retracted.len()
|
retracted: route.retracted.len()
|
||||||
});
|
});
|
||||||
|
self.update_last_hashes(&parent, hash);
|
||||||
route
|
route
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn update_last_hashes(&self, parent: &H256, hash: &H256) {
|
||||||
|
let mut hashes = self.last_hashes.write();
|
||||||
|
if hashes.front().map_or(false, |h| h == parent) {
|
||||||
|
if hashes.len() > 255 {
|
||||||
|
hashes.pop_back();
|
||||||
|
}
|
||||||
|
hashes.push_front(hash.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Import transactions from the IO queue
|
/// Import transactions from the IO queue
|
||||||
pub fn import_queued_transactions(&self, transactions: &[Bytes]) -> usize {
|
pub fn import_queued_transactions(&self, transactions: &[Bytes]) -> usize {
|
||||||
let _timer = PerfTimer::new("import_queued_transactions");
|
let _timer = PerfTimer::new("import_queued_transactions");
|
||||||
|
@ -235,6 +235,7 @@ impl State {
|
|||||||
// TODO uncomment once to_pod() works correctly.
|
// TODO uncomment once to_pod() works correctly.
|
||||||
// trace!("Applied transaction. Diff:\n{}\n", state_diff::diff_pod(&old, &self.to_pod()));
|
// trace!("Applied transaction. Diff:\n{}\n", state_diff::diff_pod(&old, &self.to_pod()));
|
||||||
self.commit();
|
self.commit();
|
||||||
|
self.clear();
|
||||||
let receipt = Receipt::new(self.root().clone(), e.cumulative_gas_used, e.logs);
|
let receipt = Receipt::new(self.root().clone(), e.cumulative_gas_used, e.logs);
|
||||||
// trace!("Transaction receipt: {:?}", receipt);
|
// trace!("Transaction receipt: {:?}", receipt);
|
||||||
Ok(ApplyOutcome{receipt: receipt, trace: e.trace})
|
Ok(ApplyOutcome{receipt: receipt, trace: e.trace})
|
||||||
@ -248,12 +249,12 @@ impl State {
|
|||||||
// TODO: is this necessary or can we dispense with the `ref mut a` for just `a`?
|
// TODO: is this necessary or can we dispense with the `ref mut a` for just `a`?
|
||||||
for (address, ref mut a) in accounts.iter_mut() {
|
for (address, ref mut a) in accounts.iter_mut() {
|
||||||
match a {
|
match a {
|
||||||
&mut&mut Some(ref mut account) => {
|
&mut&mut Some(ref mut account) if account.is_dirty() => {
|
||||||
let mut account_db = AccountDBMut::new(db, address);
|
let mut account_db = AccountDBMut::new(db, address);
|
||||||
account.commit_storage(trie_factory, &mut account_db);
|
account.commit_storage(trie_factory, &mut account_db);
|
||||||
account.commit_code(&mut account_db);
|
account.commit_code(&mut account_db);
|
||||||
}
|
}
|
||||||
&mut&mut None => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,8 +262,9 @@ impl State {
|
|||||||
let mut trie = trie_factory.from_existing(db, root).unwrap();
|
let mut trie = trie_factory.from_existing(db, root).unwrap();
|
||||||
for (address, ref a) in accounts.iter() {
|
for (address, ref a) in accounts.iter() {
|
||||||
match **a {
|
match **a {
|
||||||
Some(ref account) => trie.insert(address, &account.rlp()),
|
Some(ref account) if account.is_dirty() => trie.insert(address, &account.rlp()),
|
||||||
None => trie.remove(address),
|
None => trie.remove(address),
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -274,6 +276,11 @@ impl State {
|
|||||||
Self::commit_into(&self.trie_factory, self.db.as_hashdb_mut(), &mut self.root, self.cache.borrow_mut().deref_mut());
|
Self::commit_into(&self.trie_factory, self.db.as_hashdb_mut(), &mut self.root, self.cache.borrow_mut().deref_mut());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clear state cache
|
||||||
|
pub fn clear(&mut self) {
|
||||||
|
self.cache.borrow_mut().clear();
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[cfg(feature = "json-tests")]
|
#[cfg(feature = "json-tests")]
|
||||||
/// Populate the state from `accounts`.
|
/// Populate the state from `accounts`.
|
||||||
|
@ -177,16 +177,13 @@ impl Database {
|
|||||||
opts.set_block_based_table_factory(&block_opts);
|
opts.set_block_based_table_factory(&block_opts);
|
||||||
opts.set_prefix_extractor_fixed_size(size);
|
opts.set_prefix_extractor_fixed_size(size);
|
||||||
if let Some(cache_size) = config.cache_size {
|
if let Some(cache_size) = config.cache_size {
|
||||||
block_opts.set_cache(Cache::new(cache_size * 1024 * 256));
|
block_opts.set_cache(Cache::new(cache_size * 1024 * 1024));
|
||||||
opts.set_write_buffer_size(cache_size * 1024 * 256);
|
|
||||||
}
|
}
|
||||||
} else if let Some(cache_size) = config.cache_size {
|
} else if let Some(cache_size) = config.cache_size {
|
||||||
let mut block_opts = BlockBasedOptions::new();
|
let mut block_opts = BlockBasedOptions::new();
|
||||||
// half goes to read cache
|
// half goes to read cache
|
||||||
block_opts.set_cache(Cache::new(cache_size * 1024 * 256));
|
block_opts.set_cache(Cache::new(cache_size * 1024 * 1024));
|
||||||
opts.set_block_based_table_factory(&block_opts);
|
opts.set_block_based_table_factory(&block_opts);
|
||||||
// quarter goes to each of the two write buffers
|
|
||||||
opts.set_write_buffer_size(cache_size * 1024 * 256);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut write_opts = WriteOptions::new();
|
let mut write_opts = WriteOptions::new();
|
||||||
@ -207,12 +204,12 @@ impl Database {
|
|||||||
|
|
||||||
/// Insert a key-value pair in the transaction. Any existing value value will be overwritten.
|
/// Insert a key-value pair in the transaction. Any existing value value will be overwritten.
|
||||||
pub fn put(&self, key: &[u8], value: &[u8]) -> Result<(), String> {
|
pub fn put(&self, key: &[u8], value: &[u8]) -> Result<(), String> {
|
||||||
self.db.put(key, value)
|
self.db.put_opt(key, value, &self.write_opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delete value by key.
|
/// Delete value by key.
|
||||||
pub fn delete(&self, key: &[u8]) -> Result<(), String> {
|
pub fn delete(&self, key: &[u8]) -> Result<(), String> {
|
||||||
self.db.delete(key)
|
self.db.delete_opt(key, &self.write_opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Commit transaction to database.
|
/// Commit transaction to database.
|
||||||
|
Loading…
Reference in New Issue
Block a user