diff --git a/Cargo.lock b/Cargo.lock index af596a5c0..76eb88e91 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -663,6 +663,7 @@ dependencies = [ "grin_pow 0.2.0", "grin_store 0.2.0", "grin_util 0.2.0", + "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1064,6 +1065,11 @@ dependencies = [ "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "linked-hash-map" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "log" version = "0.3.9" @@ -1080,6 +1086,14 @@ dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "lru-cache" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "make-cmd" version = "0.1.0" @@ -2445,8 +2459,10 @@ dependencies = [ "checksum libloading 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fd38073de8f7965d0c17d30546d4bb6da311ab428d1c7a3fc71dff7f9d4979b9" "checksum librocksdb-sys 5.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1b0fa7f4ca5ceff76237db63802cb073d84e64a327e38478e79a669093fb7fa5" "checksum libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "87f737ad6cc6fd6eefe3d9dc5412f1573865bded441300904d2f42269e140f16" +"checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" +"checksum lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d06ff7ff06f729ce5f4e227876cb88d10bc59cd4ae1e09fbb2bde15c850dc21" "checksum make-cmd 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8ca8afbe8af1785e09636acb5a41e08a765f5f0340568716c18a8700ba3c0d3" "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" diff --git a/chain/Cargo.toml b/chain/Cargo.toml index 0ff7fd18c..521b874ed 100644 --- a/chain/Cargo.toml +++ b/chain/Cargo.toml @@ -12,6 +12,7 @@ slog = { version = "~2.1", features = ["max_level_trace", "release_max_level_tra serde = "1" serde_derive = "1" time = "0.1" +lru-cache = "0.1" grin_core = { path = "../core" } grin_keychain = { path = "../keychain" } diff --git a/chain/src/lib.rs b/chain/src/lib.rs index ae42a2c2b..987bdb05e 100644 --- a/chain/src/lib.rs +++ b/chain/src/lib.rs @@ -23,6 +23,7 @@ #[macro_use] extern crate bitflags; extern crate byteorder; +extern crate lru_cache; extern crate serde; #[macro_use] extern crate serde_derive; diff --git a/chain/src/store.rs b/chain/src/store.rs index dc45e5724..c116f4d44 100644 --- a/chain/src/store.rs +++ b/chain/src/store.rs @@ -14,7 +14,9 @@ //! Implements storage primitives required by the chain -use std::sync::Arc; +use std::sync::{Arc, RwLock}; + +use lru_cache::LruCache; use util::secp::pedersen::Commitment; @@ -24,6 +26,7 @@ use core::core::{Block, BlockHeader}; use core::consensus::TargetError; use core::core::target::Difficulty; use grin_store::{self, option_to_not_found, to_key, Error, u64_to_key}; +use util::LOGGER; const STORE_SUBPATH: &'static str = "chain"; @@ -41,13 +44,17 @@ const BLOCK_PMMR_FILE_METADATA_PREFIX: u8 = 'p' as u8; /// store. pub struct ChainKVStore { db: grin_store::Store, + header_cache: Arc>>, } impl ChainKVStore { /// Create new chain store pub fn new(root_path: String) -> Result { let db = grin_store::Store::open(format!("{}/{}", root_path, STORE_SUBPATH).as_str())?; - Ok(ChainKVStore { db: db }) + Ok(ChainKVStore { + db, + header_cache: Arc::new(RwLock::new(LruCache::new(100))), + }) } } @@ -113,10 +120,30 @@ impl ChainStore for ChainKVStore { } fn get_block_header(&self, h: &Hash) -> Result { - option_to_not_found( + { + let mut header_cache = self.header_cache.write().unwrap(); + + // cache hit - return the value from the cache + if let Some(header) = header_cache.get_mut(h) { + return Ok(header.clone()); + } + } + + let header: Result = option_to_not_found( self.db .get_ser(&to_key(BLOCK_HEADER_PREFIX, &mut h.to_vec())), - ) + ); + + // cache miss - so adding to the cache for next time + if let Ok(header) = header { + { + let mut header_cache = self.header_cache.write().unwrap(); + header_cache.insert(*h, header.clone()); + } + Ok(header) + } else { + header + } } /// Save the block and its header diff --git a/core/src/consensus.rs b/core/src/consensus.rs index 4eef5fd4f..d9a8794dd 100644 --- a/core/src/consensus.rs +++ b/core/src/consensus.rs @@ -227,7 +227,7 @@ where let ts_damp = if diff_sum < DAMP_FACTOR * DIFFICULTY_ADJUST_WINDOW { ts_delta } else { - (1 * ts_delta + (DAMP_FACTOR-1) * BLOCK_TIME_WINDOW) / DAMP_FACTOR + (1 * ts_delta + (DAMP_FACTOR - 1) * BLOCK_TIME_WINDOW) / DAMP_FACTOR }; // Apply time bounds