in-mem acct idx hash map uses rwlock (#19878)
This commit is contained in:
parent
fc647eed19
commit
229b378ed1
|
@ -8,7 +8,7 @@ use solana_measure::measure::Measure;
|
||||||
use solana_sdk::{clock::Slot, pubkey::Pubkey};
|
use solana_sdk::{clock::Slot, pubkey::Pubkey};
|
||||||
use std::collections::{hash_map::Entry, HashMap};
|
use std::collections::{hash_map::Entry, HashMap};
|
||||||
use std::sync::atomic::{AtomicU64, Ordering};
|
use std::sync::atomic::{AtomicU64, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::ops::RangeBounds;
|
use std::ops::RangeBounds;
|
||||||
|
@ -18,7 +18,7 @@ type K = Pubkey;
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct InMemAccountsIndex<T: IndexValue> {
|
pub struct InMemAccountsIndex<T: IndexValue> {
|
||||||
// backing store
|
// backing store
|
||||||
map: HashMap<Pubkey, AccountMapEntry<T>>,
|
map: RwLock<HashMap<Pubkey, AccountMapEntry<T>>>,
|
||||||
storage: Arc<BucketMapHolder<T>>,
|
storage: Arc<BucketMapHolder<T>>,
|
||||||
bin: usize,
|
bin: usize,
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ pub struct InMemAccountsIndex<T: IndexValue> {
|
||||||
impl<T: IndexValue> InMemAccountsIndex<T> {
|
impl<T: IndexValue> InMemAccountsIndex<T> {
|
||||||
pub fn new(storage: &AccountsIndexStorage<T>, bin: usize) -> Self {
|
pub fn new(storage: &AccountsIndexStorage<T>, bin: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
map: HashMap::new(),
|
map: RwLock::default(),
|
||||||
storage: storage.storage().clone(),
|
storage: storage.storage().clone(),
|
||||||
bin,
|
bin,
|
||||||
}
|
}
|
||||||
|
@ -41,8 +41,9 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
|
||||||
R: RangeBounds<Pubkey> + std::fmt::Debug,
|
R: RangeBounds<Pubkey> + std::fmt::Debug,
|
||||||
{
|
{
|
||||||
Self::update_stat(&self.stats().items, 1);
|
Self::update_stat(&self.stats().items, 1);
|
||||||
let mut result = Vec::with_capacity(self.map.len());
|
let map = self.map.read().unwrap();
|
||||||
self.map.iter().for_each(|(k, v)| {
|
let mut result = Vec::with_capacity(map.len());
|
||||||
|
map.iter().for_each(|(k, v)| {
|
||||||
if range.map(|range| range.contains(k)).unwrap_or(true) {
|
if range.map(|range| range.contains(k)).unwrap_or(true) {
|
||||||
result.push((*k, v.clone()));
|
result.push((*k, v.clone()));
|
||||||
}
|
}
|
||||||
|
@ -52,12 +53,12 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
|
||||||
|
|
||||||
pub fn keys(&self) -> Vec<Pubkey> {
|
pub fn keys(&self) -> Vec<Pubkey> {
|
||||||
Self::update_stat(&self.stats().keys, 1);
|
Self::update_stat(&self.stats().keys, 1);
|
||||||
self.map.keys().cloned().collect()
|
self.map.read().unwrap().keys().cloned().collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, key: &K) -> Option<AccountMapEntry<T>> {
|
pub fn get(&self, key: &K) -> Option<AccountMapEntry<T>> {
|
||||||
let m = Measure::start("get");
|
let m = Measure::start("get");
|
||||||
let result = self.map.get(key).cloned();
|
let result = self.map.read().unwrap().get(key).cloned();
|
||||||
let stats = self.stats();
|
let stats = self.stats();
|
||||||
let (count, time) = if result.is_some() {
|
let (count, time) = if result.is_some() {
|
||||||
(&stats.gets_from_mem, &stats.get_mem_us)
|
(&stats.gets_from_mem, &stats.get_mem_us)
|
||||||
|
@ -73,7 +74,8 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
|
||||||
// Return false otherwise.
|
// Return false otherwise.
|
||||||
pub fn remove_if_slot_list_empty(&mut self, pubkey: Pubkey) -> bool {
|
pub fn remove_if_slot_list_empty(&mut self, pubkey: Pubkey) -> bool {
|
||||||
let m = Measure::start("entry");
|
let m = Measure::start("entry");
|
||||||
let entry = self.map.entry(pubkey);
|
let mut map = self.map.write().unwrap();
|
||||||
|
let entry = map.entry(pubkey);
|
||||||
let stats = &self.storage.stats;
|
let stats = &self.storage.stats;
|
||||||
let (count, time) = if matches!(entry, Entry::Occupied(_)) {
|
let (count, time) = if matches!(entry, Entry::Occupied(_)) {
|
||||||
(&stats.entries_from_mem, &stats.entry_mem_us)
|
(&stats.entries_from_mem, &stats.entry_mem_us)
|
||||||
|
@ -101,7 +103,8 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
|
||||||
previous_slot_entry_was_cached: bool,
|
previous_slot_entry_was_cached: bool,
|
||||||
) {
|
) {
|
||||||
let m = Measure::start("entry");
|
let m = Measure::start("entry");
|
||||||
let entry = self.map.entry(*pubkey);
|
let mut map = self.map.write().unwrap();
|
||||||
|
let entry = map.entry(*pubkey);
|
||||||
let stats = &self.storage.stats;
|
let stats = &self.storage.stats;
|
||||||
let (count, time) = if matches!(entry, Entry::Occupied(_)) {
|
let (count, time) = if matches!(entry, Entry::Occupied(_)) {
|
||||||
(&stats.entries_from_mem, &stats.entry_mem_us)
|
(&stats.entries_from_mem, &stats.entry_mem_us)
|
||||||
|
@ -194,7 +197,7 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
|
||||||
reclaims: &mut SlotList<T>,
|
reclaims: &mut SlotList<T>,
|
||||||
previous_slot_entry_was_cached: bool,
|
previous_slot_entry_was_cached: bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if let Some(current) = self.map.get(pubkey) {
|
if let Some(current) = self.map.read().unwrap().get(pubkey) {
|
||||||
Self::lock_and_update_slot_list(
|
Self::lock_and_update_slot_list(
|
||||||
current,
|
current,
|
||||||
new_value,
|
new_value,
|
||||||
|
@ -208,7 +211,7 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.map.len()
|
self.map.read().unwrap().len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
|
@ -223,7 +226,8 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
|
||||||
new_entry: AccountMapEntry<T>,
|
new_entry: AccountMapEntry<T>,
|
||||||
) -> Option<(WriteAccountMapEntry<T>, T, Pubkey)> {
|
) -> Option<(WriteAccountMapEntry<T>, T, Pubkey)> {
|
||||||
let m = Measure::start("entry");
|
let m = Measure::start("entry");
|
||||||
let entry = self.map.entry(pubkey);
|
let mut map = self.map.write().unwrap();
|
||||||
|
let entry = map.entry(pubkey);
|
||||||
let stats = &self.storage.stats;
|
let stats = &self.storage.stats;
|
||||||
let (count, time) = if matches!(entry, Entry::Occupied(_)) {
|
let (count, time) = if matches!(entry, Entry::Occupied(_)) {
|
||||||
(&stats.entries_from_mem, &stats.entry_mem_us)
|
(&stats.entries_from_mem, &stats.entry_mem_us)
|
||||||
|
|
Loading…
Reference in New Issue