1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
//! Some stats from a completed simulation.
use dslab_core::Id;
use serde::{Deserialize, Serialize};
/// Some stats from a completed simulation.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RunStats {
/// Total time between first [NewDag](crate::runner::NewDag) event and last simulation event.
pub total_makespan: f64,
/// Total number of received DAGs.
pub total_dag_count: usize,
/// Total number of completed DAGs.
pub completed_dag_count: usize,
/// Average makespan of a DAG among completed DAGs.
pub average_dag_makespan: f64,
/// Minimum makespan of a DAG among completed DAGs.
pub min_dag_makespan: f64,
/// Maximum makespan of a DAG among completed DAGs.
pub max_dag_makespan: f64,
/// Total CPU flops used by all completed tasks.
pub total_cpu_flops: f64,
/// Average CPU utilization during simulation.
pub cpu_utilization: f64,
/// Average memory utilization during simulation.
pub memory_utilization: f64,
/// Total network traffic. Includes transfers with `src == dst`.
pub total_network_traffic: f64,
/// Total network traffic between different racks.
pub network_traffic_between_racks: f64,
/// Total network traffic between different hosts.
pub network_traffic_between_hosts: f64,
/// Total number chunks in DFS in the end of the simulation.
pub total_chunks_in_dfs: u64,
/// Fraction of the used space in the end of the simulation.
pub total_space_used: f64,
#[serde(skip)]
total_cores: u32,
#[serde(skip)]
total_memory: u64,
}
impl RunStats {
/// Initialize new stats for a system with given number of cores and amount of memory.
pub fn new(total_cores: u32, total_memory: u64) -> Self {
RunStats {
total_makespan: 0.0,
total_dag_count: 0,
completed_dag_count: 0,
average_dag_makespan: 0.0,
min_dag_makespan: f64::MAX,
max_dag_makespan: 0.0,
total_cpu_flops: 0.0,
cpu_utilization: 0.0,
memory_utilization: 0.0,
total_network_traffic: 0.0,
network_traffic_between_racks: 0.0,
network_traffic_between_hosts: 0.0,
total_cores,
total_memory,
total_chunks_in_dfs: 0,
total_space_used: 0.0,
}
}
/// Register completed DAG with given makespan.
pub fn register_dag(&mut self, makespan: f64) {
self.average_dag_makespan = (self.average_dag_makespan * self.completed_dag_count as f64 + makespan)
/ (self.completed_dag_count + 1) as f64;
self.completed_dag_count += 1;
self.max_dag_makespan = self.max_dag_makespan.max(makespan);
self.min_dag_makespan = self.min_dag_makespan.min(makespan);
}
/// Register completed transfer with given parameters.
/// * `size` --- size of the data which was transfered.
/// * `src`, `dst` --- pairs (simulation component, rack) for transfer source and destination.
pub fn register_transfer(&mut self, size: f64, src: (Id, usize), dst: (Id, usize)) {
let (src, src_rack) = src;
let (dst, dst_rack) = dst;
self.total_network_traffic += size;
if src != dst {
self.network_traffic_between_hosts += size;
}
if src_rack != dst_rack {
self.network_traffic_between_racks += size;
}
}
/// Register task with a given computation size.
pub fn register_task_execution(&mut self, flops: f64) {
self.total_cpu_flops += flops;
}
/// Register CPU utilization measure in `(number of cores used) * (time of the usage)`.
pub fn register_cpu_utilization(&mut self, cpu_utilization: f64) {
self.cpu_utilization += cpu_utilization / self.total_cores as f64;
}
/// Register memory utilization measure in `(amount of memory used) * (time of the usage)`.
pub fn register_memory_utilization(&mut self, memory_utilization: f64) {
self.memory_utilization += memory_utilization / self.total_memory as f64;
}
/// Finalize result given [total_makespan](RunStats::total_makespan);
pub fn finalize(&mut self, makespan: f64) {
self.total_makespan = makespan;
self.cpu_utilization /= makespan;
self.memory_utilization /= makespan;
}
}