solana_core/repair/
packet_threshold.rs

1use std::time::Duration;
2
3enum PacketThresholdUpdate {
4    Increase,
5    Decrease,
6}
7
8impl PacketThresholdUpdate {
9    const PERCENTAGE: usize = 90;
10
11    fn calculate(&self, current: usize) -> usize {
12        match *self {
13            PacketThresholdUpdate::Increase => {
14                current.saturating_mul(100).saturating_div(Self::PERCENTAGE)
15            }
16            PacketThresholdUpdate::Decrease => {
17                current.saturating_mul(Self::PERCENTAGE).saturating_div(100)
18            }
19        }
20    }
21}
22
23#[derive(Debug)]
24pub struct DynamicPacketToProcessThreshold {
25    max_packets: usize,
26}
27
28impl Default for DynamicPacketToProcessThreshold {
29    fn default() -> Self {
30        Self {
31            max_packets: Self::DEFAULT_MAX_PACKETS,
32        }
33    }
34}
35
36impl DynamicPacketToProcessThreshold {
37    const DEFAULT_MAX_PACKETS: usize = 1024;
38    const TIME_THRESHOLD: Duration = Duration::from_secs(1);
39
40    pub fn update(&mut self, total_packets: usize, compute_time: Duration) {
41        if total_packets >= self.max_packets {
42            let threshold_update = if compute_time > Self::TIME_THRESHOLD {
43                PacketThresholdUpdate::Decrease
44            } else {
45                PacketThresholdUpdate::Increase
46            };
47            self.max_packets = threshold_update.calculate(self.max_packets);
48        }
49    }
50
51    pub fn should_drop(&self, total: usize) -> bool {
52        total >= self.max_packets
53    }
54}
55
56#[cfg(test)]
57mod test {
58    use {super::DynamicPacketToProcessThreshold, std::time::Duration};
59
60    #[test]
61    fn test_dynamic_packet_threshold() {
62        let mut threshold = DynamicPacketToProcessThreshold::default();
63        assert_eq!(
64            threshold.max_packets,
65            DynamicPacketToProcessThreshold::DEFAULT_MAX_PACKETS
66        );
67
68        assert!(!threshold.should_drop(10));
69        assert!(threshold.should_drop(2000));
70
71        let old = threshold.max_packets;
72
73        // Increase
74        let total = 2000;
75        let compute_time = Duration::from_millis(500);
76        threshold.update(total, compute_time);
77        assert!(threshold.max_packets > old);
78
79        // Decrease
80        let compute_time = Duration::from_millis(2000);
81        threshold.update(total, compute_time);
82        assert_eq!(threshold.max_packets, old - 1); // due to rounding error, there is a difference of 1
83    }
84}