Optional network capacity in simulations (#483)
* Make simulation net capacity optional * Add cli flag to disable netcap
This commit is contained in:
parent
61ff62cb29
commit
d479721efd
|
@ -46,6 +46,8 @@ pub struct SimulationApp {
|
||||||
log_to: log::LogOutput,
|
log_to: log::LogOutput,
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
dump_overlay_info: bool,
|
dump_overlay_info: bool,
|
||||||
|
#[clap(long)]
|
||||||
|
no_netcap: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SimulationApp {
|
impl SimulationApp {
|
||||||
|
@ -56,6 +58,7 @@ impl SimulationApp {
|
||||||
log_format: _,
|
log_format: _,
|
||||||
log_to: _,
|
log_to: _,
|
||||||
dump_overlay_info,
|
dump_overlay_info,
|
||||||
|
no_netcap,
|
||||||
} = self;
|
} = self;
|
||||||
let simulation_settings: SimulationSettings = load_json_from_file(&input_settings)?;
|
let simulation_settings: SimulationSettings = load_json_from_file(&input_settings)?;
|
||||||
|
|
||||||
|
@ -99,14 +102,19 @@ impl SimulationApp {
|
||||||
// Dividing milliseconds in second by milliseconds in the step.
|
// Dividing milliseconds in second by milliseconds in the step.
|
||||||
let step_time_as_second_fraction =
|
let step_time_as_second_fraction =
|
||||||
simulation_settings.step_time.subsec_millis() as f32 / 1_000_000_f32;
|
simulation_settings.step_time.subsec_millis() as f32 / 1_000_000_f32;
|
||||||
let capacity_bps = simulation_settings.node_settings.network_capacity_kbps as f32
|
let capacity_bps = if no_netcap {
|
||||||
* 1024.0
|
None
|
||||||
* step_time_as_second_fraction;
|
} else {
|
||||||
|
simulation_settings
|
||||||
|
.node_settings
|
||||||
|
.network_capacity_kbps
|
||||||
|
.map(|c| (c as f32 * 1024.0 * step_time_as_second_fraction) as u32)
|
||||||
|
};
|
||||||
let network_message_receiver = {
|
let network_message_receiver = {
|
||||||
let mut network = network.lock();
|
let mut network = network.lock();
|
||||||
network.connect(
|
network.connect(
|
||||||
node_id,
|
node_id,
|
||||||
capacity_bps as u32,
|
capacity_bps,
|
||||||
node_message_receiver,
|
node_message_receiver,
|
||||||
node_message_broadcast_receiver,
|
node_message_broadcast_receiver,
|
||||||
)
|
)
|
||||||
|
|
|
@ -109,13 +109,13 @@ mod network_behaviors_serde {
|
||||||
/// Represents node network capacity and current load in bytes.
|
/// Represents node network capacity and current load in bytes.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct NodeNetworkCapacity {
|
struct NodeNetworkCapacity {
|
||||||
capacity_bps: u32,
|
capacity_bps: Option<u32>,
|
||||||
current_load: Mutex<u32>,
|
current_load: Mutex<u32>,
|
||||||
load_to_flush: AtomicU32,
|
load_to_flush: AtomicU32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeNetworkCapacity {
|
impl NodeNetworkCapacity {
|
||||||
fn new(capacity_bps: u32) -> Self {
|
fn new(capacity_bps: Option<u32>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
capacity_bps,
|
capacity_bps,
|
||||||
current_load: Mutex::new(0),
|
current_load: Mutex::new(0),
|
||||||
|
@ -124,12 +124,16 @@ impl NodeNetworkCapacity {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn increase_load(&self, load: u32) -> bool {
|
fn increase_load(&self, load: u32) -> bool {
|
||||||
let mut current_load = self.current_load.lock();
|
if let Some(capacity_bps) = self.capacity_bps {
|
||||||
if *current_load + load <= self.capacity_bps {
|
let mut current_load = self.current_load.lock();
|
||||||
*current_load += load;
|
if *current_load + load <= capacity_bps {
|
||||||
true
|
*current_load += load;
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
false
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,6 +142,10 @@ impl NodeNetworkCapacity {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush_load(&self) {
|
fn flush_load(&self) {
|
||||||
|
if self.capacity_bps.is_none() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let mut s = self.current_load.lock();
|
let mut s = self.current_load.lock();
|
||||||
*s -= self.load_to_flush.load(Ordering::Relaxed);
|
*s -= self.load_to_flush.load(Ordering::Relaxed);
|
||||||
self.load_to_flush.store(0, Ordering::Relaxed);
|
self.load_to_flush.store(0, Ordering::Relaxed);
|
||||||
|
@ -188,7 +196,7 @@ where
|
||||||
pub fn connect(
|
pub fn connect(
|
||||||
&mut self,
|
&mut self,
|
||||||
node_id: NodeId,
|
node_id: NodeId,
|
||||||
capacity_bps: u32,
|
capacity_bps: Option<u32>,
|
||||||
node_message_receiver: Receiver<NetworkMessage<M>>,
|
node_message_receiver: Receiver<NetworkMessage<M>>,
|
||||||
node_message_broadcast_receiver: Receiver<NetworkMessage<M>>,
|
node_message_broadcast_receiver: Receiver<NetworkMessage<M>>,
|
||||||
) -> Receiver<NetworkMessage<M>> {
|
) -> Receiver<NetworkMessage<M>> {
|
||||||
|
@ -301,20 +309,24 @@ where
|
||||||
message: &NetworkMessage<M>,
|
message: &NetworkMessage<M>,
|
||||||
to: &NodeId,
|
to: &NodeId,
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
let mut cap = node_capacity.current_load.lock();
|
if let Some(capacity_bps) = node_capacity.capacity_bps {
|
||||||
let sent = node_capacity.capacity_bps - *cap;
|
let mut cap = node_capacity.current_load.lock();
|
||||||
*cap = node_capacity.capacity_bps;
|
let sent = capacity_bps - *cap;
|
||||||
let remaining = message.partial_send(sent);
|
*cap = capacity_bps;
|
||||||
// Message is partially sent, the node capacity needs to be flushed at the end of step even
|
let remaining = message.partial_send(sent);
|
||||||
// if the whole message is not sent.
|
// Message is partially sent, the node capacity needs to be flushed at the end of step even
|
||||||
node_capacity.decrease_load(sent);
|
// if the whole message is not sent.
|
||||||
if remaining == 0 {
|
node_capacity.decrease_load(sent);
|
||||||
let to_node = self.to_node_senders.get(to).unwrap();
|
if remaining == 0 {
|
||||||
to_node
|
let to_node = self.to_node_senders.get(to).unwrap();
|
||||||
.send(message.clone())
|
to_node
|
||||||
.expect("node should have connection");
|
.send(message.clone())
|
||||||
|
.expect("node should have connection");
|
||||||
|
}
|
||||||
|
remaining
|
||||||
|
} else {
|
||||||
|
0
|
||||||
}
|
}
|
||||||
remaining
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -484,7 +496,8 @@ mod tests {
|
||||||
|
|
||||||
let (from_a_sender, from_a_receiver) = channel::unbounded();
|
let (from_a_sender, from_a_receiver) = channel::unbounded();
|
||||||
let (from_a_broadcast_sender, from_a_broadcast_receiver) = channel::unbounded();
|
let (from_a_broadcast_sender, from_a_broadcast_receiver) = channel::unbounded();
|
||||||
let to_a_receiver = network.connect(node_a, 3, from_a_receiver, from_a_broadcast_receiver);
|
let to_a_receiver =
|
||||||
|
network.connect(node_a, Some(3), from_a_receiver, from_a_broadcast_receiver);
|
||||||
let a = MockNetworkInterface::new(
|
let a = MockNetworkInterface::new(
|
||||||
node_a,
|
node_a,
|
||||||
from_a_broadcast_sender,
|
from_a_broadcast_sender,
|
||||||
|
@ -495,7 +508,8 @@ mod tests {
|
||||||
|
|
||||||
let (from_b_sender, from_b_receiver) = channel::unbounded();
|
let (from_b_sender, from_b_receiver) = channel::unbounded();
|
||||||
let (from_b_broadcast_sender, from_b_broadcast_receiver) = channel::unbounded();
|
let (from_b_broadcast_sender, from_b_broadcast_receiver) = channel::unbounded();
|
||||||
let to_b_receiver = network.connect(node_b, 3, from_b_receiver, from_b_broadcast_receiver);
|
let to_b_receiver =
|
||||||
|
network.connect(node_b, Some(3), from_b_receiver, from_b_broadcast_receiver);
|
||||||
let b = MockNetworkInterface::new(
|
let b = MockNetworkInterface::new(
|
||||||
node_b,
|
node_b,
|
||||||
from_b_broadcast_sender,
|
from_b_broadcast_sender,
|
||||||
|
@ -561,7 +575,8 @@ mod tests {
|
||||||
|
|
||||||
let (from_a_sender, from_a_receiver) = channel::unbounded();
|
let (from_a_sender, from_a_receiver) = channel::unbounded();
|
||||||
let (from_a_broadcast_sender, from_a_broadcast_receiver) = channel::unbounded();
|
let (from_a_broadcast_sender, from_a_broadcast_receiver) = channel::unbounded();
|
||||||
let to_a_receiver = network.connect(node_a, 2, from_a_receiver, from_a_broadcast_receiver);
|
let to_a_receiver =
|
||||||
|
network.connect(node_a, Some(2), from_a_receiver, from_a_broadcast_receiver);
|
||||||
let a = MockNetworkInterface::new(
|
let a = MockNetworkInterface::new(
|
||||||
node_a,
|
node_a,
|
||||||
from_a_broadcast_sender,
|
from_a_broadcast_sender,
|
||||||
|
@ -572,7 +587,8 @@ mod tests {
|
||||||
|
|
||||||
let (from_b_sender, from_b_receiver) = channel::unbounded();
|
let (from_b_sender, from_b_receiver) = channel::unbounded();
|
||||||
let (from_b_broadcast_sender, from_b_broadcast_receiver) = channel::unbounded();
|
let (from_b_broadcast_sender, from_b_broadcast_receiver) = channel::unbounded();
|
||||||
let to_b_receiver = network.connect(node_b, 2, from_b_receiver, from_b_broadcast_receiver);
|
let to_b_receiver =
|
||||||
|
network.connect(node_b, Some(2), from_b_receiver, from_b_broadcast_receiver);
|
||||||
let b = MockNetworkInterface::new(
|
let b = MockNetworkInterface::new(
|
||||||
node_b,
|
node_b,
|
||||||
from_b_broadcast_sender,
|
from_b_broadcast_sender,
|
||||||
|
@ -583,7 +599,8 @@ mod tests {
|
||||||
|
|
||||||
let (from_c_sender, from_c_receiver) = channel::unbounded();
|
let (from_c_sender, from_c_receiver) = channel::unbounded();
|
||||||
let (from_c_broadcast_sender, from_c_broadcast_receiver) = channel::unbounded();
|
let (from_c_broadcast_sender, from_c_broadcast_receiver) = channel::unbounded();
|
||||||
let to_c_receiver = network.connect(node_c, 2, from_c_receiver, from_c_broadcast_receiver);
|
let to_c_receiver =
|
||||||
|
network.connect(node_c, Some(2), from_c_receiver, from_c_broadcast_receiver);
|
||||||
let c = MockNetworkInterface::new(
|
let c = MockNetworkInterface::new(
|
||||||
node_c,
|
node_c,
|
||||||
from_c_broadcast_sender,
|
from_c_broadcast_sender,
|
||||||
|
@ -639,7 +656,8 @@ mod tests {
|
||||||
|
|
||||||
let (from_a_sender, from_a_receiver) = channel::unbounded();
|
let (from_a_sender, from_a_receiver) = channel::unbounded();
|
||||||
let (from_a_broadcast_sender, from_a_broadcast_receiver) = channel::unbounded();
|
let (from_a_broadcast_sender, from_a_broadcast_receiver) = channel::unbounded();
|
||||||
let to_a_receiver = network.connect(node_a, 3, from_a_receiver, from_a_broadcast_receiver);
|
let to_a_receiver =
|
||||||
|
network.connect(node_a, Some(3), from_a_receiver, from_a_broadcast_receiver);
|
||||||
let a = MockNetworkInterface::new(
|
let a = MockNetworkInterface::new(
|
||||||
node_a,
|
node_a,
|
||||||
from_a_broadcast_sender,
|
from_a_broadcast_sender,
|
||||||
|
@ -650,7 +668,8 @@ mod tests {
|
||||||
|
|
||||||
let (from_b_sender, from_b_receiver) = channel::unbounded();
|
let (from_b_sender, from_b_receiver) = channel::unbounded();
|
||||||
let (from_b_broadcast_sender, from_b_broadcast_receiver) = channel::unbounded();
|
let (from_b_broadcast_sender, from_b_broadcast_receiver) = channel::unbounded();
|
||||||
let to_b_receiver = network.connect(node_b, 2, from_b_receiver, from_b_broadcast_receiver);
|
let to_b_receiver =
|
||||||
|
network.connect(node_b, Some(2), from_b_receiver, from_b_broadcast_receiver);
|
||||||
let b = MockNetworkInterface::new(
|
let b = MockNetworkInterface::new(
|
||||||
node_b,
|
node_b,
|
||||||
from_b_broadcast_sender,
|
from_b_broadcast_sender,
|
||||||
|
@ -677,6 +696,53 @@ mod tests {
|
||||||
assert_eq!(b.receive_messages().len(), 2);
|
assert_eq!(b.receive_messages().len(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn node_network_capacity_no_limit() {
|
||||||
|
let node_a = NodeId::from_index(0);
|
||||||
|
let node_b = NodeId::from_index(1);
|
||||||
|
|
||||||
|
let regions = HashMap::from([(Region::Europe, vec![node_a, node_b])]);
|
||||||
|
let behaviour = HashMap::from([(
|
||||||
|
NetworkBehaviourKey::new(Region::Europe, Region::Europe),
|
||||||
|
NetworkBehaviour::new(Duration::from_millis(100), 0.0),
|
||||||
|
)]);
|
||||||
|
let regions_data = RegionsData::new(regions, behaviour);
|
||||||
|
let mut network = Network::new(regions_data, 0);
|
||||||
|
|
||||||
|
let (from_a_sender, from_a_receiver) = channel::unbounded();
|
||||||
|
let (from_a_broadcast_sender, from_a_broadcast_receiver) = channel::unbounded();
|
||||||
|
let to_a_receiver =
|
||||||
|
network.connect(node_a, None, from_a_receiver, from_a_broadcast_receiver);
|
||||||
|
let a = MockNetworkInterface::new(
|
||||||
|
node_a,
|
||||||
|
from_a_broadcast_sender,
|
||||||
|
from_a_sender,
|
||||||
|
to_a_receiver,
|
||||||
|
1000,
|
||||||
|
);
|
||||||
|
|
||||||
|
let (from_b_sender, from_b_receiver) = channel::unbounded();
|
||||||
|
let (from_b_broadcast_sender, from_b_broadcast_receiver) = channel::unbounded();
|
||||||
|
let to_b_receiver =
|
||||||
|
network.connect(node_b, None, from_b_receiver, from_b_broadcast_receiver);
|
||||||
|
let b = MockNetworkInterface::new(
|
||||||
|
node_b,
|
||||||
|
from_b_broadcast_sender,
|
||||||
|
from_b_sender,
|
||||||
|
to_b_receiver,
|
||||||
|
100,
|
||||||
|
);
|
||||||
|
|
||||||
|
for _ in 0..6 {
|
||||||
|
a.send_message(node_b, ());
|
||||||
|
b.send_message(node_a, ());
|
||||||
|
}
|
||||||
|
|
||||||
|
network.step(Duration::from_millis(100));
|
||||||
|
assert_eq!(a.receive_messages().len(), 6);
|
||||||
|
assert_eq!(b.receive_messages().len(), 6);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn node_network_message_partial_send() {
|
fn node_network_message_partial_send() {
|
||||||
let node_a = NodeId::from_index(0);
|
let node_a = NodeId::from_index(0);
|
||||||
|
@ -694,7 +760,8 @@ mod tests {
|
||||||
let (from_a_broadcast_sender, from_a_broadcast_receiver) = channel::unbounded();
|
let (from_a_broadcast_sender, from_a_broadcast_receiver) = channel::unbounded();
|
||||||
|
|
||||||
// Node A is connected to the network with throuput of 5.
|
// Node A is connected to the network with throuput of 5.
|
||||||
let to_a_receiver = network.connect(node_a, 5, from_a_receiver, from_a_broadcast_receiver);
|
let to_a_receiver =
|
||||||
|
network.connect(node_a, Some(5), from_a_receiver, from_a_broadcast_receiver);
|
||||||
|
|
||||||
// Every message sent **from** Node A will be of size 15.
|
// Every message sent **from** Node A will be of size 15.
|
||||||
let a = MockNetworkInterface::new(
|
let a = MockNetworkInterface::new(
|
||||||
|
@ -709,7 +776,8 @@ mod tests {
|
||||||
let (from_b_broadcast_sender, from_b_broadcast_receiver) = channel::unbounded();
|
let (from_b_broadcast_sender, from_b_broadcast_receiver) = channel::unbounded();
|
||||||
|
|
||||||
// Node B is connected to the network with throuput of 1.
|
// Node B is connected to the network with throuput of 1.
|
||||||
let to_b_receiver = network.connect(node_b, 1, from_b_receiver, from_b_broadcast_receiver);
|
let to_b_receiver =
|
||||||
|
network.connect(node_b, Some(1), from_b_receiver, from_b_broadcast_receiver);
|
||||||
|
|
||||||
// Every message sent **from** Node B will be of size 2.
|
// Every message sent **from** Node B will be of size 2.
|
||||||
let b = MockNetworkInterface::new(
|
let b = MockNetworkInterface::new(
|
||||||
|
|
|
@ -482,7 +482,7 @@ mod tests {
|
||||||
channel::unbounded();
|
channel::unbounded();
|
||||||
let network_message_receiver = network.connect(
|
let network_message_receiver = network.connect(
|
||||||
*node_id,
|
*node_id,
|
||||||
0,
|
None,
|
||||||
node_message_receiver,
|
node_message_receiver,
|
||||||
node_message_broadcast_receiver,
|
node_message_broadcast_receiver,
|
||||||
);
|
);
|
||||||
|
|
|
@ -116,7 +116,7 @@ mod tests {
|
||||||
channel::unbounded();
|
channel::unbounded();
|
||||||
let network_message_receiver = network.connect(
|
let network_message_receiver = network.connect(
|
||||||
*node_id,
|
*node_id,
|
||||||
1,
|
Some(1),
|
||||||
node_message_receiver,
|
node_message_receiver,
|
||||||
node_message_broadcast_receiver,
|
node_message_broadcast_receiver,
|
||||||
);
|
);
|
||||||
|
|
|
@ -43,7 +43,7 @@ pub struct BranchSettings {
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
|
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
|
||||||
pub struct NodeSettings {
|
pub struct NodeSettings {
|
||||||
pub network_capacity_kbps: u32,
|
pub network_capacity_kbps: Option<u32>,
|
||||||
#[serde(with = "humantime_serde")]
|
#[serde(with = "humantime_serde")]
|
||||||
pub timeout: std::time::Duration,
|
pub timeout: std::time::Duration,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue