dscale 0.5.2

A fast & deterministic simulation framework for benchmarking and testing distributed systems
Documentation
use crate::{MessagePtr, Pid, jiffy::Jiffies};

/// Per-process NIC bandwidth configuration.
#[derive(Clone, Copy, Default)]
pub enum BandwidthConfig {
    /// No bandwidth limit (messages are delivered after latency only).
    #[default]
    Unbounded,

    /// Limits throughput to the given number of bytes per jiffy.
    Bounded(usize),
}

pub(crate) struct Bandwidth {
    bandwidth: usize,
    total_pased: Vec<usize>,
}

impl Bandwidth {
    pub(crate) fn new(bandwidth_type: BandwidthConfig, proc_num: usize) -> Self {
        let bandwidth = match bandwidth_type {
            BandwidthConfig::Unbounded => usize::MAX,
            BandwidthConfig::Bounded(bound) => bound,
        };

        Self {
            bandwidth,
            total_pased: vec![0; proc_num + 1],
        }
    }

    pub(crate) fn try_pass(
        &mut self,
        message: &MessagePtr,
        target: Pid,
        now: Jiffies,
    ) -> Option<Jiffies> {
        if self.bandwidth == usize::MAX {
            // No bandwidth -> no extra latency
            return None;
        }

        let message_size = message.virtual_size();

        let new_total = self.total_pased[target] + message_size;

        if new_total > now.0 * self.bandwidth {
            self.add_passed(message_size, target);
            return Some(Jiffies(new_total / self.bandwidth));
        }

        None
    }

    pub(crate) fn add_passed(&mut self, how_much: usize, target: Pid) {
        self.total_pased[target] += how_much
    }
}