Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit d66c472

Browse files
authored
Improve shared state cache contention (#9321)
1 parent b7dbfb2 commit d66c472

File tree

2 files changed

+41
-32
lines changed

2 files changed

+41
-32
lines changed

client/db/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1643,7 +1643,7 @@ impl<Block: BlockT> Backend<Block> {
16431643
self.changes_tries_storage.post_commit(changes_trie_cache_ops);
16441644

16451645
if let Some((enacted, retracted)) = cache_update {
1646-
self.shared_cache.lock().sync(&enacted, &retracted);
1646+
self.shared_cache.write().sync(&enacted, &retracted);
16471647
}
16481648

16491649
for m in meta_updates {
@@ -2052,7 +2052,7 @@ impl<Block: BlockT> sc_client_api::backend::Backend<Block> for Backend<Block> {
20522052
);
20532053
let database_cache = MemorySize::from_bytes(0);
20542054
let state_cache = MemorySize::from_bytes(
2055-
(*&self.shared_cache).lock().used_storage_cache_size(),
2055+
(*&self.shared_cache).read().used_storage_cache_size(),
20562056
);
20572057
let state_db = self.storage.state_db.memory_info();
20582058

client/db/src/storage_cache.rs

+39-30
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
use std::collections::{VecDeque, HashSet, HashMap};
2424
use std::sync::Arc;
2525
use std::hash::Hash as StdHash;
26-
use parking_lot::{Mutex, RwLock, RwLockUpgradableReadGuard};
26+
use parking_lot::{RwLock, RwLockUpgradableReadGuard};
2727
use linked_hash_map::{LinkedHashMap, Entry};
2828
use hash_db::Hasher;
2929
use sp_runtime::traits::{Block as BlockT, Header, HashFor, NumberFor};
@@ -222,7 +222,7 @@ impl<B: BlockT> Cache<B> {
222222
}
223223
}
224224

225-
pub type SharedCache<B> = Arc<Mutex<Cache<B>>>;
225+
pub type SharedCache<B> = Arc<RwLock<Cache<B>>>;
226226

227227
/// Fix lru storage size for hash (small 64ko).
228228
const FIX_LRU_HASH_SIZE: usize = 65_536;
@@ -234,7 +234,7 @@ pub fn new_shared_cache<B: BlockT>(
234234
) -> SharedCache<B> {
235235
let top = child_ratio.1.saturating_sub(child_ratio.0);
236236
Arc::new(
237-
Mutex::new(
237+
RwLock::new(
238238
Cache {
239239
lru_storage: LRUMap(
240240
LinkedHashMap::new(), 0, shared_cache_size * top / child_ratio.1
@@ -337,7 +337,7 @@ impl<B: BlockT> CacheChanges<B> {
337337
commit_number: Option<NumberFor<B>>,
338338
is_best: bool,
339339
) {
340-
let mut cache = self.shared_cache.lock();
340+
let mut cache = self.shared_cache.write();
341341
trace!(
342342
"Syncing cache, id = (#{:?}, {:?}), parent={:?}, best={}",
343343
commit_number,
@@ -527,12 +527,15 @@ impl<S: StateBackend<HashFor<B>>, B: BlockT> StateBackend<HashFor<B>> for Cachin
527527

528528
return Ok(entry)
529529
}
530-
let mut cache = self.cache.shared_cache.lock();
531-
if Self::is_allowed(Some(key), None, &self.cache.parent_hash, &cache.modifications) {
532-
if let Some(entry) = cache.lru_storage.get(key).map(|a| a.clone()) {
533-
trace!("Found in shared cache: {:?}", HexDisplay::from(&key));
534-
self.usage.tally_key_read(key, entry.as_ref(), true);
535-
return Ok(entry)
530+
{
531+
let cache = self.cache.shared_cache.upgradable_read();
532+
if Self::is_allowed(Some(key), None, &self.cache.parent_hash, &cache.modifications) {
533+
let mut cache = RwLockUpgradableReadGuard::upgrade(cache);
534+
if let Some(entry) = cache.lru_storage.get(key).map(|a| a.clone()) {
535+
trace!("Found in shared cache: {:?}", HexDisplay::from(&key));
536+
self.usage.tally_key_read(key, entry.as_ref(), true);
537+
return Ok(entry)
538+
}
536539
}
537540
}
538541
trace!("Cache miss: {:?}", HexDisplay::from(&key));
@@ -548,11 +551,14 @@ impl<S: StateBackend<HashFor<B>>, B: BlockT> StateBackend<HashFor<B>> for Cachin
548551
trace!("Found hash in local cache: {:?}", HexDisplay::from(&key));
549552
return Ok(entry)
550553
}
551-
let mut cache = self.cache.shared_cache.lock();
552-
if Self::is_allowed(Some(key), None, &self.cache.parent_hash, &cache.modifications) {
553-
if let Some(entry) = cache.lru_hashes.get(key).map(|a| a.0.clone()) {
554-
trace!("Found hash in shared cache: {:?}", HexDisplay::from(&key));
555-
return Ok(entry)
554+
{
555+
let cache = self.cache.shared_cache.upgradable_read();
556+
if Self::is_allowed(Some(key), None, &self.cache.parent_hash, &cache.modifications) {
557+
let mut cache = RwLockUpgradableReadGuard::upgrade(cache);
558+
if let Some(entry) = cache.lru_hashes.get(key).map(|a| a.0.clone()) {
559+
trace!("Found hash in shared cache: {:?}", HexDisplay::from(&key));
560+
return Ok(entry)
561+
}
556562
}
557563
}
558564
trace!("Cache hash miss: {:?}", HexDisplay::from(&key));
@@ -574,13 +580,16 @@ impl<S: StateBackend<HashFor<B>>, B: BlockT> StateBackend<HashFor<B>> for Cachin
574580
self.usage.tally_child_key_read(&key, entry, true)
575581
)
576582
}
577-
let mut cache = self.cache.shared_cache.lock();
578-
if Self::is_allowed(None, Some(&key), &self.cache.parent_hash, &cache.modifications) {
579-
if let Some(entry) = cache.lru_child_storage.get(&key).map(|a| a.clone()) {
580-
trace!("Found in shared cache: {:?}", key);
581-
return Ok(
582-
self.usage.tally_child_key_read(&key, entry, true)
583-
)
583+
{
584+
let cache = self.cache.shared_cache.upgradable_read();
585+
if Self::is_allowed(None, Some(&key), &self.cache.parent_hash, &cache.modifications) {
586+
let mut cache = RwLockUpgradableReadGuard::upgrade(cache);
587+
if let Some(entry) = cache.lru_child_storage.get(&key).map(|a| a.clone()) {
588+
trace!("Found in shared cache: {:?}", key);
589+
return Ok(
590+
self.usage.tally_child_key_read(&key, entry, true)
591+
)
592+
}
584593
}
585594
}
586595
trace!("Cache miss: {:?}", key);
@@ -1274,7 +1283,7 @@ mod tests {
12741283
true,
12751284
);
12761285
// 32 key, 3 byte size
1277-
assert_eq!(shared.lock().used_storage_cache_size(), 35 /* bytes */);
1286+
assert_eq!(shared.read().used_storage_cache_size(), 35 /* bytes */);
12781287

12791288
let key = H256::random()[..].to_vec();
12801289
s.cache.sync_cache(
@@ -1287,7 +1296,7 @@ mod tests {
12871296
true,
12881297
);
12891298
// 35 + (2 * 32) key, 2 byte size
1290-
assert_eq!(shared.lock().used_storage_cache_size(), 101 /* bytes */);
1299+
assert_eq!(shared.read().used_storage_cache_size(), 101 /* bytes */);
12911300
}
12921301

12931302
#[test]
@@ -1313,7 +1322,7 @@ mod tests {
13131322
true,
13141323
);
13151324
// 32 key, 4 byte size
1316-
assert_eq!(shared.lock().used_storage_cache_size(), 36 /* bytes */);
1325+
assert_eq!(shared.read().used_storage_cache_size(), 36 /* bytes */);
13171326

13181327
let key = H256::random()[..].to_vec();
13191328
s.cache.sync_cache(
@@ -1326,7 +1335,7 @@ mod tests {
13261335
true,
13271336
);
13281337
// 32 key, 2 byte size
1329-
assert_eq!(shared.lock().used_storage_cache_size(), 34 /* bytes */);
1338+
assert_eq!(shared.read().used_storage_cache_size(), 34 /* bytes */);
13301339
}
13311340

13321341
#[test]
@@ -1379,7 +1388,7 @@ mod tests {
13791388

13801389
// Restart (or unknown block?), clear caches.
13811390
{
1382-
let mut cache = s.cache.shared_cache.lock();
1391+
let mut cache = s.cache.shared_cache.write();
13831392
let cache = &mut *cache;
13841393
cache.lru_storage.clear();
13851394
cache.lru_hashes.clear();
@@ -1426,7 +1435,7 @@ mod tests {
14261435
Some(1),
14271436
true,
14281437
);
1429-
assert_eq!(shared.lock().lru_storage.get(&key).unwrap(), &Some(vec![1]));
1438+
assert_eq!(shared.write().lru_storage.get(&key).unwrap(), &Some(vec![1]));
14301439

14311440
let mut s = CachingState::new(
14321441
InMemoryBackend::<BlakeTwo256>::default(),
@@ -1445,7 +1454,7 @@ mod tests {
14451454
false,
14461455
);
14471456

1448-
assert_eq!(shared.lock().lru_storage.get(&key).unwrap(), &Some(vec![1]));
1457+
assert_eq!(shared.write().lru_storage.get(&key).unwrap(), &Some(vec![1]));
14491458

14501459
let mut s = CachingState::new(
14511460
InMemoryBackend::<BlakeTwo256>::default(),
@@ -1800,7 +1809,7 @@ mod qc {
18001809

18011810
std::mem::swap(fork_chain, &mut new_fork);
18021811

1803-
self.shared.lock().sync(&retracted, &enacted);
1812+
self.shared.write().sync(&retracted, &enacted);
18041813

18051814
self.head_state(
18061815
self.canon.last()

0 commit comments

Comments
 (0)