cache manager and clearing tracing cache (#1769)
* removed configure_cache method * generic cache_manager struct * fixed #1743, tracing caches are cleared * removed deadlocks in garbage_collect, implemented HeapSizeOf for traces * trace cache config * fixed carbage typo
This commit is contained in:
69
ethcore/src/cache_manager.rs
Normal file
69
ethcore/src/cache_manager.rs
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::collections::{VecDeque, HashSet};
|
||||
use std::hash::Hash;
|
||||
|
||||
const COLLECTION_QUEUE_SIZE: usize = 8;
|
||||
|
||||
pub struct CacheManager<T> where T: Eq + Hash {
|
||||
pref_cache_size: usize,
|
||||
max_cache_size: usize,
|
||||
bytes_per_cache_entry: usize,
|
||||
cache_usage: VecDeque<HashSet<T>>
|
||||
}
|
||||
|
||||
impl<T> CacheManager<T> where T: Eq + Hash {
|
||||
pub fn new(pref_cache_size: usize, max_cache_size: usize, bytes_per_cache_entry: usize) -> Self {
|
||||
CacheManager {
|
||||
pref_cache_size: pref_cache_size,
|
||||
max_cache_size: max_cache_size,
|
||||
bytes_per_cache_entry: bytes_per_cache_entry,
|
||||
cache_usage: (0..COLLECTION_QUEUE_SIZE).into_iter().map(|_| Default::default()).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn note_used(&mut self, id: T) {
|
||||
if !self.cache_usage[0].contains(&id) {
|
||||
if let Some(c) = self.cache_usage.iter_mut().skip(1).find(|e| e.contains(&id)) {
|
||||
c.remove(&id);
|
||||
}
|
||||
self.cache_usage[0].insert(id);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn collect_garbage<C, F>(&mut self, current_size: C, mut notify_unused: F) where C: Fn() -> usize, F: FnMut(HashSet<T>) {
|
||||
if current_size() < self.pref_cache_size {
|
||||
self.rotate_cache_if_needed();
|
||||
return;
|
||||
}
|
||||
|
||||
for _ in 0..COLLECTION_QUEUE_SIZE {
|
||||
notify_unused(self.cache_usage.pop_back().unwrap());
|
||||
self.cache_usage.push_front(Default::default());
|
||||
if current_size() < self.max_cache_size {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn rotate_cache_if_needed(&mut self) {
|
||||
if self.cache_usage[0].len() * self.bytes_per_cache_entry > self.pref_cache_size / COLLECTION_QUEUE_SIZE {
|
||||
let cache = self.cache_usage.pop_back().unwrap();
|
||||
self.cache_usage.push_front(cache);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user