shares the lock on gossip when processing prune messages (#13339)
Processing prune messages acquires an exclusive lock on gossip: https://github.com/solana-labs/solana/blob/55b0428ff/core/src/cluster_info.rs#L1824-L1825 This can be reduced to a shared lock if active-sets are changed to use atomic bloom filters: https://github.com/solana-labs/solana/blob/55b0428ff/core/src/crds_gossip_push.rs#L50
This commit is contained in:
@ -539,7 +539,7 @@ impl ClusterInfo {
|
||||
|
||||
// Should only be used by tests and simulations
|
||||
pub fn clone_with_id(&self, new_id: &Pubkey) -> Self {
|
||||
let mut gossip = self.gossip.read().unwrap().clone();
|
||||
let mut gossip = self.gossip.read().unwrap().mock_clone();
|
||||
gossip.id = *new_id;
|
||||
let mut my_contact_info = self.my_contact_info.read().unwrap().clone();
|
||||
my_contact_info.id = *new_id;
|
||||
@ -1856,8 +1856,7 @@ impl ClusterInfo {
|
||||
let mut prune_message_timeout = 0;
|
||||
let mut bad_prune_destination = 0;
|
||||
{
|
||||
let mut gossip =
|
||||
self.time_gossip_write_lock("process_prune", &self.stats.process_prune);
|
||||
let gossip = self.time_gossip_read_lock("process_prune", &self.stats.process_prune);
|
||||
let now = timestamp();
|
||||
for (from, data) in messages {
|
||||
match gossip.process_prune_msg(
|
||||
|
@ -17,7 +17,6 @@ use std::collections::{HashMap, HashSet};
|
||||
///The min size for bloom filters
|
||||
pub const CRDS_GOSSIP_DEFAULT_BLOOM_ITEMS: usize = 500;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CrdsGossip {
|
||||
pub crds: Crds,
|
||||
pub id: Pubkey,
|
||||
@ -108,7 +107,7 @@ impl CrdsGossip {
|
||||
|
||||
/// add the `from` to the peer's filter of nodes
|
||||
pub fn process_prune_msg(
|
||||
&mut self,
|
||||
&self,
|
||||
peer: &Pubkey,
|
||||
destination: &Pubkey,
|
||||
origin: &[Pubkey],
|
||||
@ -266,6 +265,16 @@ impl CrdsGossip {
|
||||
self.pull.purge_failed_inserts(now);
|
||||
rv
|
||||
}
|
||||
|
||||
// Only for tests and simulations.
|
||||
pub(crate) fn mock_clone(&self) -> Self {
|
||||
Self {
|
||||
crds: self.crds.clone(),
|
||||
push: self.push.mock_clone(),
|
||||
pull: self.pull.clone(),
|
||||
..*self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes a normalized(log of actual stake) stake
|
||||
|
@ -20,7 +20,7 @@ use bincode::serialized_size;
|
||||
use indexmap::map::IndexMap;
|
||||
use itertools::Itertools;
|
||||
use rand::{seq::SliceRandom, Rng};
|
||||
use solana_runtime::bloom::Bloom;
|
||||
use solana_runtime::bloom::{AtomicBloom, Bloom};
|
||||
use solana_sdk::{hash::Hash, packet::PACKET_DATA_SIZE, pubkey::Pubkey, timing::timestamp};
|
||||
use std::{
|
||||
cmp,
|
||||
@ -42,12 +42,11 @@ const PUSH_ACTIVE_TIMEOUT_MS: u64 = 60_000;
|
||||
// 10 minutes
|
||||
const MAX_PUSHED_TO_TIMEOUT_MS: u64 = 10 * 60 * 1000;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CrdsGossipPush {
|
||||
/// max bytes per message
|
||||
pub max_bytes: usize,
|
||||
/// active set of validators for push
|
||||
active_set: IndexMap<Pubkey, Bloom<Pubkey>>,
|
||||
active_set: IndexMap<Pubkey, AtomicBloom<Pubkey>>,
|
||||
/// push message queue
|
||||
push_messages: HashMap<CrdsValueLabel, Hash>,
|
||||
/// Cache that tracks which validators a message was received from
|
||||
@ -287,11 +286,11 @@ impl CrdsGossipPush {
|
||||
}
|
||||
|
||||
/// add the `from` to the peer's filter of nodes
|
||||
pub fn process_prune_msg(&mut self, self_pubkey: &Pubkey, peer: &Pubkey, origins: &[Pubkey]) {
|
||||
if let Some(peer) = self.active_set.get_mut(peer) {
|
||||
pub fn process_prune_msg(&self, self_pubkey: &Pubkey, peer: &Pubkey, origins: &[Pubkey]) {
|
||||
if let Some(filter) = self.active_set.get(peer) {
|
||||
for origin in origins {
|
||||
if origin != self_pubkey {
|
||||
peer.add(origin);
|
||||
filter.add(origin);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -348,7 +347,7 @@ impl CrdsGossipPush {
|
||||
continue;
|
||||
}
|
||||
let size = cmp::max(CRDS_GOSSIP_DEFAULT_BLOOM_ITEMS, network_size);
|
||||
let mut bloom = Bloom::random(size, 0.1, 1024 * 8 * 4);
|
||||
let bloom: AtomicBloom<_> = Bloom::random(size, 0.1, 1024 * 8 * 4).into();
|
||||
bloom.add(&item.id);
|
||||
new_items.insert(item.id, bloom);
|
||||
}
|
||||
@ -427,6 +426,21 @@ impl CrdsGossipPush {
|
||||
!v.is_empty()
|
||||
});
|
||||
}
|
||||
|
||||
// Only for tests and simulations.
|
||||
pub(crate) fn mock_clone(&self) -> Self {
|
||||
let mut active_set = IndexMap::<Pubkey, AtomicBloom<Pubkey>>::new();
|
||||
for (k, v) in &self.active_set {
|
||||
active_set.insert(*k, v.mock_clone());
|
||||
}
|
||||
Self {
|
||||
active_set,
|
||||
push_messages: self.push_messages.clone(),
|
||||
received_cache: self.received_cache.clone(),
|
||||
last_pushed_to: self.last_pushed_to.clone(),
|
||||
..*self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
Reference in New Issue
Block a user