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:
behzad nouri
2020-11-05 15:42:00 +00:00
committed by GitHub
parent bc62313c66
commit 8f0796436a
6 changed files with 86 additions and 22 deletions

View File

@ -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(

View File

@ -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

View File

@ -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)]