diff --git a/framework/src/io/pmd.rs b/framework/src/io/pmd.rs index 4bd14add0f..5a59411d76 100644 --- a/framework/src/io/pmd.rs +++ b/framework/src/io/pmd.rs @@ -2,6 +2,7 @@ use super::mbuf::MBuf; use super::interface::Result; use super::interface::ZCSIError; use super::super::headers::MacAddress; +use std::fmt; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -74,6 +75,12 @@ pub struct PortQueue { _pad1: [u64; 4] } +impl fmt::Display for PortQueue { + fn fmt(&self, f:&mut fmt::Formatter) -> fmt::Result { + write!(f, "port {} txq {} rxq {}", self.port_id, self.txq, self.rxq) + } +} + impl Drop for PmdPort { fn drop(&mut self) { if self.connected && self.should_close { diff --git a/framework/src/packet_batch/receive_batch.rs b/framework/src/packet_batch/receive_batch.rs index 9adb3c744e..849db2469c 100644 --- a/framework/src/packet_batch/receive_batch.rs +++ b/framework/src/packet_batch/receive_batch.rs @@ -1,3 +1,4 @@ +extern crate time; use io::PortQueue; use io::Result; use super::act::Act; @@ -11,6 +12,7 @@ pub struct ReceiveBatch { parent: PacketBatch, port: PortQueue, pub received: u64, + batch: u64, } impl ReceiveBatch { @@ -19,6 +21,7 @@ impl ReceiveBatch { parent: parent, port: port, received: 0, + batch: 0, } } @@ -27,6 +30,7 @@ impl ReceiveBatch { parent: PacketBatch::new(32), port: port, received: 0, + batch: 0, } } @@ -77,6 +81,14 @@ impl Act for ReceiveBatch { .recv(&mut self.port) .and_then(|x| { self.received += x as u64; + if x > 0 { + self.batch += 1; + if self.batch > 100000 { + let time = time::precise_time_ns(); + println!("rx {} {} {}", self.port, self.batch, time); + self.batch = 0; + } + } Ok(x) }) .expect("Receive failed"); diff --git a/framework/src/packet_batch/send_batch.rs b/framework/src/packet_batch/send_batch.rs index ef7f6f423e..89057d58a1 100644 --- a/framework/src/packet_batch/send_batch.rs +++ b/framework/src/packet_batch/send_batch.rs @@ -1,3 +1,4 @@ +extern crate time; use io::PortQueue; use io::Result; use super::act::Act; @@ -14,6 +15,7 @@ pub struct SendBatch port: PortQueue, parent: V, pub sent: u64, + batch: u64, } impl SendBatch @@ -24,6 +26,7 @@ impl SendBatch port: port, sent: 0, parent: parent, + batch: 0, } } } @@ -75,6 +78,14 @@ impl Act for SendBatch .send_q(&mut self.port) .and_then(|x| { self.sent += x as u64; + if x > 0 { + self.batch += x as u64; + if self.batch > 3_200_000 { + let time = time::precise_time_ns(); + println!("tx {} {} {}", self.port, self.batch, time); + self.batch = 0; + } + } Ok(x) }) .expect("Send failed"); diff --git a/framework/src/scheduler/scheduler.rs b/framework/src/scheduler/scheduler.rs index 9fbbd9718a..7069087da1 100644 --- a/framework/src/scheduler/scheduler.rs +++ b/framework/src/scheduler/scheduler.rs @@ -1,3 +1,4 @@ +extern crate time; use super::Executable; use std::cell::RefCell; /// A very simple round-robin scheduler. This should really be more of a DRR scheduler. @@ -38,15 +39,31 @@ impl Scheduler { /// Run the scheduling loop. // TODO: Add a variable to stop the scheduler (for whatever reason). + #[inline] pub fn execute_loop(&mut self) { if !self.run_q.is_empty() { loop {self.execute_internal()} } } + #[inline] pub fn execute_one(&mut self) { if !self.run_q.is_empty() { self.execute_internal() } } + + #[inline] + pub fn execute_loop_timed(&mut self, pfx: &str, batch: usize) { + if !self.run_q.is_empty() { + loop { + let start = time::precise_time_ns(); + for _ in 0..batch { + self.execute_internal() + } + let end = time::precise_time_ns(); + println!("{} Time for {} batches was {}", pfx, batch, end - start); + } + } + } } diff --git a/test/chain-test/src/main.rs b/test/chain-test/src/main.rs index cd7ca0f3f2..d69bcc306c 100644 --- a/test/chain-test/src/main.rs +++ b/test/chain-test/src/main.rs @@ -21,7 +21,7 @@ mod nf; const CONVERSION_FACTOR: f64 = 1000000000.; -fn recv_thread(ports: Vec, core: i32, chain_len: u32) { +fn recv_thread(ports: Vec, core: i32, chain_len: u32, cycles: bool) { init_thread(core, core); println!("Receiving started"); for port in &ports { @@ -44,7 +44,12 @@ fn recv_thread(ports: Vec, core: i32, chain_len: u32) { for pipeline in pipelines { sched.add_task(RefCell::new(pipeline as Box)); } - sched.execute_loop(); + if !cycles { + sched.execute_loop(); + } else { + let pfx = format!("{} ", core); + sched.execute_loop_timed(&pfx[..], 10000); + } } fn main() { @@ -59,6 +64,7 @@ fn main() { opts.optmulti("c", "core", "Core to use", "core"); opts.optopt("m", "master", "Master core", "master"); opts.optopt("l", "chain", "Chain length", "length"); + opts.optflag("", "cpp", "Measure cycles per packet"); let matches = match opts.parse(&args[1..]) { Ok(m) => m, Err(f) => panic!(f.to_string()), @@ -94,6 +100,7 @@ fn main() { } let primary = !matches.opt_present("secondary"); + let measure_cycles = matches.opt_present("cpp"); let cores_for_port = if primary { extract_cores_for_port(&matches.opt_strs("w"), &cores) @@ -142,7 +149,7 @@ fn main() { .map(|(core, ports)| { let c = core.clone(); let p: Vec<_> = ports.iter().map(|p| p.clone()).collect(); - std::thread::spawn(move || recv_thread(p, c, chain_len)) + std::thread::spawn(move || recv_thread(p, c, chain_len, measure_cycles)) }) .collect(); let mut pkts_so_far = (0, 0);