add block header cache to store (#996)

* WIP - add blocks header cache to store
The DifficultyIter is expensive to use when validating block headers.

* lru_cache

* rustfmt

* cleanup
This commit is contained in:
Antioch Peverell 2018-04-23 14:55:25 -04:00 committed by GitHub
parent 7cc4fdfed9
commit ef304ee9c1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 50 additions and 5 deletions

16
Cargo.lock generated
View file

@ -663,6 +663,7 @@ dependencies = [
"grin_pow 0.2.0", "grin_pow 0.2.0",
"grin_store 0.2.0", "grin_store 0.2.0",
"grin_util 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)", "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 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)", "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)", "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]] [[package]]
name = "log" name = "log"
version = "0.3.9" version = "0.3.9"
@ -1080,6 +1086,14 @@ dependencies = [
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "make-cmd" name = "make-cmd"
version = "0.1.0" 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 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 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 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.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 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 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 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" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"

View file

@ -12,6 +12,7 @@ slog = { version = "~2.1", features = ["max_level_trace", "release_max_level_tra
serde = "1" serde = "1"
serde_derive = "1" serde_derive = "1"
time = "0.1" time = "0.1"
lru-cache = "0.1"
grin_core = { path = "../core" } grin_core = { path = "../core" }
grin_keychain = { path = "../keychain" } grin_keychain = { path = "../keychain" }

View file

@ -23,6 +23,7 @@
#[macro_use] #[macro_use]
extern crate bitflags; extern crate bitflags;
extern crate byteorder; extern crate byteorder;
extern crate lru_cache;
extern crate serde; extern crate serde;
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;

View file

@ -14,7 +14,9 @@
//! Implements storage primitives required by the chain //! 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; use util::secp::pedersen::Commitment;
@ -24,6 +26,7 @@ use core::core::{Block, BlockHeader};
use core::consensus::TargetError; use core::consensus::TargetError;
use core::core::target::Difficulty; use core::core::target::Difficulty;
use grin_store::{self, option_to_not_found, to_key, Error, u64_to_key}; use grin_store::{self, option_to_not_found, to_key, Error, u64_to_key};
use util::LOGGER;
const STORE_SUBPATH: &'static str = "chain"; const STORE_SUBPATH: &'static str = "chain";
@ -41,13 +44,17 @@ const BLOCK_PMMR_FILE_METADATA_PREFIX: u8 = 'p' as u8;
/// store. /// store.
pub struct ChainKVStore { pub struct ChainKVStore {
db: grin_store::Store, db: grin_store::Store,
header_cache: Arc<RwLock<LruCache<Hash, BlockHeader>>>,
} }
impl ChainKVStore { impl ChainKVStore {
/// Create new chain store /// Create new chain store
pub fn new(root_path: String) -> Result<ChainKVStore, Error> { pub fn new(root_path: String) -> Result<ChainKVStore, Error> {
let db = grin_store::Store::open(format!("{}/{}", root_path, STORE_SUBPATH).as_str())?; 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<BlockHeader, Error> { fn get_block_header(&self, h: &Hash) -> Result<BlockHeader, Error> {
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<BlockHeader, Error> = option_to_not_found(
self.db self.db
.get_ser(&to_key(BLOCK_HEADER_PREFIX, &mut h.to_vec())), .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 /// Save the block and its header