mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
perf(net): cap backoff duration and only apply to severe backoff kinds (#2022)
This commit is contained in:
@ -347,7 +347,7 @@ impl PeersManager {
|
||||
// reset the peer's state
|
||||
// we reset the backoff counter since we're able to establish a successful
|
||||
// session to that peer
|
||||
entry.get_mut().backoff_counter = 0;
|
||||
entry.get_mut().severe_backoff_counter = 0;
|
||||
entry.get_mut().state = PeerConnectionState::Idle;
|
||||
return
|
||||
}
|
||||
@ -415,10 +415,12 @@ impl PeersManager {
|
||||
if let Some(mut peer) = self.peers.get_mut(peer_id) {
|
||||
let reputation_change = if let Some(kind) = err.should_backoff() {
|
||||
// Increment peer.backoff_counter
|
||||
peer.backoff_counter += 1;
|
||||
if kind.is_severe() {
|
||||
peer.severe_backoff_counter += 1;
|
||||
}
|
||||
|
||||
let backoff_time =
|
||||
self.backoff_durations.backoff_until(kind, peer.backoff_counter);
|
||||
self.backoff_durations.backoff_until(kind, peer.severe_backoff_counter);
|
||||
|
||||
backoff_until = Some(backoff_time);
|
||||
|
||||
@ -766,8 +768,8 @@ pub struct Peer {
|
||||
remove_after_disconnect: bool,
|
||||
/// The kind of peer
|
||||
kind: PeerKind,
|
||||
/// Counts number of times the peer was backed off
|
||||
backoff_counter: u32,
|
||||
/// Counts number of times the peer was backed off due to a severe [BackoffKind].
|
||||
severe_backoff_counter: u32,
|
||||
}
|
||||
|
||||
// === impl Peer ===
|
||||
@ -789,7 +791,7 @@ impl Peer {
|
||||
fork_id: None,
|
||||
remove_after_disconnect: false,
|
||||
kind: Default::default(),
|
||||
backoff_counter: 0,
|
||||
severe_backoff_counter: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1071,6 +1073,9 @@ pub struct PeerBackoffDurations {
|
||||
/// Intended for spammers, or bad peers in general.
|
||||
#[cfg_attr(feature = "serde", serde(with = "humantime_serde"))]
|
||||
pub high: Duration,
|
||||
/// Maximum total backoff duration.
|
||||
#[cfg_attr(feature = "serde", serde(with = "humantime_serde"))]
|
||||
pub max: Duration,
|
||||
}
|
||||
|
||||
impl PeerBackoffDurations {
|
||||
@ -1083,11 +1088,14 @@ impl PeerBackoffDurations {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the timestamp until which we should backoff
|
||||
/// Returns the timestamp until which we should backoff.
|
||||
///
|
||||
/// The Backoff duration is capped by the configured maximum backoff duration.
|
||||
pub fn backoff_until(&self, kind: BackoffKind, backoff_counter: u32) -> std::time::Instant {
|
||||
let backoff_time = self.backoff(kind) * backoff_counter;
|
||||
let backoff_time = self.backoff(kind);
|
||||
let backoff_time = backoff_time + backoff_time * backoff_counter;
|
||||
let now = std::time::Instant::now();
|
||||
now + backoff_time
|
||||
now + backoff_time.min(self.max)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1099,6 +1107,8 @@ impl Default for PeerBackoffDurations {
|
||||
medium: Duration::from_secs(60 * 3),
|
||||
// 15min
|
||||
high: Duration::from_secs(60 * 15),
|
||||
// 1h
|
||||
max: Duration::from_secs(60 * 60),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1375,6 +1385,23 @@ mod test {
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_low_backoff() {
|
||||
let peer = PeerId::random();
|
||||
let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
|
||||
let config = PeersConfig::default();
|
||||
let mut peers = PeersManager::new(config);
|
||||
peers.add_peer(peer, socket_addr, None);
|
||||
let peer_struct = peers.peers.get_mut(&peer).unwrap();
|
||||
|
||||
let backoff_timestamp = peers
|
||||
.backoff_durations
|
||||
.backoff_until(BackoffKind::Low, peer_struct.severe_backoff_counter);
|
||||
|
||||
let expected = std::time::Instant::now() + peers.backoff_durations.low;
|
||||
assert!(backoff_timestamp <= expected);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_multiple_backoff_calculations() {
|
||||
let peer = PeerId::random();
|
||||
@ -1385,15 +1412,16 @@ mod test {
|
||||
let peer_struct = peers.peers.get_mut(&peer).unwrap();
|
||||
|
||||
// Simulate a peer that was already backed off once
|
||||
peer_struct.backoff_counter = 1;
|
||||
peer_struct.severe_backoff_counter = 1;
|
||||
|
||||
let now = std::time::Instant::now();
|
||||
|
||||
// Simulate the increment that happens in on_connection_failure
|
||||
peer_struct.backoff_counter += 1;
|
||||
peer_struct.severe_backoff_counter += 1;
|
||||
// Get official backoff time
|
||||
let backoff_time =
|
||||
peers.backoff_durations.backoff_until(BackoffKind::High, peer_struct.backoff_counter);
|
||||
let backoff_time = peers
|
||||
.backoff_durations
|
||||
.backoff_until(BackoffKind::High, peer_struct.severe_backoff_counter);
|
||||
|
||||
// Duration of the backoff should be 2 * 15 minutes = 30 minutes
|
||||
let backoff_duration = std::time::Duration::new(30 * 60, 0);
|
||||
|
||||
Reference in New Issue
Block a user