Skip to content

Commit

Permalink
Replace the Vec<_> by BTreeSet / BTreeMap in the storage.
Browse files Browse the repository at this point in the history
  • Loading branch information
MathieuDutSik committed Sep 26, 2024
1 parent 5e8bfa5 commit e24f4e6
Showing 1 changed file with 57 additions and 159 deletions.
216 changes: 57 additions & 159 deletions linera-views/src/backends/lru_caching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub const DEFAULT_CACHE_POLICY: LruCachePolicy = LruCachePolicy {
#[cfg(with_metrics)]
use std::sync::LazyLock;
use std::{
collections::{btree_map, hash_map::RandomState, BTreeMap},
collections::{btree_map, hash_map::RandomState, BTreeMap, BTreeSet},
sync::{Arc, Mutex},
};

Expand All @@ -39,7 +39,7 @@ use crate::memory::MemoryStore;
use crate::{
batch::{Batch, WriteOperation},
common::{
get_interval, get_upper_bound_option, KeyIterable, KeyValueIterable, ReadableKeyValueStore,
get_interval, KeyIterable, KeyValueIterable, ReadableKeyValueStore,
RestrictedKeyValueStore, WithError, WritableKeyValueStore,
},
};
Expand Down Expand Up @@ -171,209 +171,105 @@ impl ValueCacheEntry {
}

enum FindCacheEntry {
Keys(Vec<Vec<u8>>),
KeyValues(Vec<(Vec<u8>, Vec<u8>)>),
Keys(BTreeSet<Vec<u8>>),
KeyValues(BTreeMap<Vec<u8>, Vec<u8>>),
}

impl FindCacheEntry {
fn get_find_keys(&self, key_prefix: &[u8]) -> Vec<Vec<u8>> {
let key_prefix = key_prefix.to_vec();
let delta = key_prefix.len();
let mut keys = Vec::new();
match self {
FindCacheEntry::Keys(vec) => {
let start_pos = match vec.binary_search(&key_prefix) {
Ok(pos) => pos,
Err(pos) => pos,
};
let end_pos = match get_upper_bound_option(&key_prefix) {
None => vec.len(),
Some(upper) => match vec.binary_search(&upper) {
Ok(pos) => pos,
Err(pos) => pos,
},
};
for key in &vec[start_pos..end_pos] {
keys.push(key[delta..].to_vec());
}
let mut keys_test = Vec::new();
for key in vec {
if key.starts_with(&key_prefix) {
let key_red = key[delta..].to_vec();
keys_test.push(key_red);
}
}
assert_eq!(keys_test, keys);
}
FindCacheEntry::KeyValues(vec) => {
let start_pos = match vec.binary_search_by(|(probe, _)| probe.cmp(&key_prefix)) {
Ok(pos) => pos,
Err(pos) => pos,
};
let end_pos = match get_upper_bound_option(&key_prefix) {
None => vec.len(),
Some(upper) => match vec.binary_search_by(|(probe, _)| probe.cmp(&upper)) {
Ok(pos) => pos,
Err(pos) => pos,
},
};
for (key, _) in &vec[start_pos..end_pos] {
keys.push(key[delta..].to_vec());
}
}
FindCacheEntry::Keys(map) => map
.range(get_interval(key_prefix))
.map(|key| key[delta..].to_vec())
.collect::<Vec<_>>(),
FindCacheEntry::KeyValues(map) => map
.range(get_interval(key_prefix))
.map(|(key, _)| key[delta..].to_vec())
.collect::<Vec<_>>(),
}
keys
}

fn get_find_key_values(&self, key_prefix: &[u8]) -> Option<Vec<(Vec<u8>, Vec<u8>)>> {
match self {
FindCacheEntry::Keys(_) => None,
FindCacheEntry::KeyValues(vec) => {
FindCacheEntry::KeyValues(map) => {
let key_prefix = key_prefix.to_vec();
let delta = key_prefix.len();
let mut key_values = Vec::new();
let start_pos = match vec.binary_search_by(|(probe, _)| probe.cmp(&key_prefix)) {
Ok(pos) => pos,
Err(pos) => pos,
};
let end_pos = match get_upper_bound_option(&key_prefix) {
None => vec.len(),
Some(upper) => match vec.binary_search_by(|(probe, _)| probe.cmp(&upper)) {
Ok(pos) => pos,
Err(pos) => pos,
},
};
for (key, value) in &vec[start_pos..end_pos] {
let key_value = (key[delta..].to_vec(), value.clone());
key_values.push(key_value);
}
let mut key_values_test = Vec::new();
for (key, value) in vec {
if key.starts_with(&key_prefix) {
let key_value = (key[delta..].to_vec(), value.clone());
key_values_test.push(key_value);
}
}
assert_eq!(key_values_test, key_values);
Some(key_values)
Some(
map.range(get_interval(key_prefix))
.map(|(key, value)| (key[delta..].to_vec(), value.to_vec()))
.collect::<Vec<_>>(),
)
}
}
}

fn get_contains_key(&self, key: &[u8]) -> bool {
let key = key.to_vec();
match self {
FindCacheEntry::Keys(vec) => {
let result = vec.binary_search(&key);
result.is_ok()
}
FindCacheEntry::KeyValues(vec) => {
let result = vec.binary_search_by(|(probe, _)| probe.cmp(&key));
result.is_ok()
}
FindCacheEntry::Keys(map) => map.contains(key),
FindCacheEntry::KeyValues(map) => map.contains_key(key),
}
}

fn get_read_value(&self, key: &[u8]) -> Option<Option<Vec<u8>>> {
let key = key.to_vec();
match self {
FindCacheEntry::Keys(_vec) => None,
FindCacheEntry::KeyValues(vec) => {
let result = vec.binary_search_by(|(probe, _)| probe.cmp(&key));
match result {
Ok(pos) => Some(Some(vec[pos].1.clone())),
Err(_) => Some(None),
}
}
FindCacheEntry::Keys(_map) => None,
FindCacheEntry::KeyValues(map) => Some(map.get(key).cloned()),
}
}

fn update_cache_entry(&mut self, key: &[u8], new_value: Option<Vec<u8>>) {
let key = key.to_vec();
match self {
FindCacheEntry::Keys(vec) => {
let result = vec.binary_search(&key);
match result {
Ok(pos) => match new_value {
None => {
vec.remove(pos);
}
Some(_) => {
vec[pos] = key;
}
},
Err(pos) => {
if new_value.is_some() {
vec.insert(pos, key);
}
}
}
FindCacheEntry::Keys(map) => {
match new_value {
None => map.remove(key),
Some(_) => map.insert(key.to_vec()),
};
}
FindCacheEntry::KeyValues(vec) => {
let result = vec.binary_search_by(|(probe, _)| probe.cmp(&key));
match result {
Ok(pos) => match new_value {
None => {
vec.remove(pos);
}
Some(new_value) => {
vec[pos] = (key, new_value);
}
},
Err(pos) => {
if let Some(new_value) = new_value {
vec.insert(pos, (key, new_value));
}
}
}
FindCacheEntry::KeyValues(map) => {
match new_value {
None => map.remove(key),
Some(new_value) => map.insert(key.to_vec(), new_value),
};
}
}
}

fn delete_prefix(&mut self, key_prefix: &[u8]) {
let key_prefix = key_prefix.to_vec();
match self {
FindCacheEntry::Keys(vec) => {
let start_pos = match vec.binary_search(&key_prefix) {
Ok(pos) => pos,
Err(pos) => pos,
};
let end_pos = match get_upper_bound_option(&key_prefix) {
None => vec.len(),
Some(upper) => match vec.binary_search(&upper) {
Ok(pos) => pos,
Err(pos) => pos,
},
};
vec.drain(start_pos..end_pos);
FindCacheEntry::Keys(map) => {
let keys = map
.range(get_interval(key_prefix.to_vec()))
.cloned()
.collect::<Vec<_>>();
for key in keys {
map.remove(&key);
}
}
FindCacheEntry::KeyValues(vec) => {
let start_pos = match vec.binary_search_by(|(probe, _)| probe.cmp(&key_prefix)) {
Ok(pos) => pos,
Err(pos) => pos,
};
let end_pos = match get_upper_bound_option(&key_prefix) {
None => vec.len(),
Some(upper) => match vec.binary_search_by(|(probe, _)| probe.cmp(&upper)) {
Ok(pos) => pos,
Err(pos) => pos,
},
};
vec.drain(start_pos..end_pos);
FindCacheEntry::KeyValues(map) => {
let keys = map
.range(get_interval(key_prefix.to_vec()))
.map(|(key, _)| key.clone())
.collect::<Vec<_>>();
for key in keys {
map.remove(&key);
}
}
}
}

fn size(&self) -> usize {
let mut total_size = 0;
match self {
FindCacheEntry::Keys(vec) => {
for key in vec {
FindCacheEntry::Keys(map) => {
for key in map {
total_size += key.len();
}
}
FindCacheEntry::KeyValues(vec) => {
for (key, value) in vec {
FindCacheEntry::KeyValues(map) => {
for (key, value) in map {
total_size += key.len() + value.len();
}
}
Expand Down Expand Up @@ -570,13 +466,15 @@ impl LruPrefixCache {

/// Inserts a find entry into the cache.
pub fn insert_find_keys(&mut self, key_prefix: Vec<u8>, value: &[Vec<u8>]) {
let cache_entry = FindCacheEntry::Keys(value.to_owned());
let map = value.iter().cloned().collect::<BTreeSet<_>>();
let cache_entry = FindCacheEntry::Keys(map);
self.insert_find(key_prefix, cache_entry);
}

/// Inserts a find_key_values entry into the cache.
pub fn insert_find_key_values(&mut self, key_prefix: Vec<u8>, value: &[(Vec<u8>, Vec<u8>)]) {
let cache_entry = FindCacheEntry::KeyValues(value.to_owned());
let map = value.iter().cloned().collect::<BTreeMap<_, _>>();
let cache_entry = FindCacheEntry::KeyValues(map);
self.insert_find(key_prefix, cache_entry);
}

Expand All @@ -588,7 +486,7 @@ impl LruPrefixCache {
cache_entries.push((key.clone(), CacheEntry::Value));
}
for (key, value) in self.map_find.range_mut(get_interval(key_prefix.to_vec())) {
*value = FindCacheEntry::KeyValues(Vec::new());
*value = FindCacheEntry::KeyValues(BTreeMap::new());
cache_entries.push((key.clone(), CacheEntry::Find));
}
for cache_entry in cache_entries {
Expand Down

0 comments on commit e24f4e6

Please sign in to comment.