mirror of
https://github.com/Zenithsiz/ftmemsim.git
synced 2026-02-13 22:36:58 +00:00
Pin trace reading is now done as-needed instead of up-front.
This commit is contained in:
16
src/main.rs
16
src/main.rs
@@ -13,7 +13,7 @@ mod util;
|
||||
|
||||
// Imports
|
||||
use {
|
||||
self::{args::Args, pin_trace::PinTrace},
|
||||
self::{args::Args, pin_trace::PinTraceReader},
|
||||
crate::{classifiers::hemem, sim::Simulator, util::FemtoDuration},
|
||||
anyhow::Context,
|
||||
clap::Parser,
|
||||
@@ -29,11 +29,9 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
logger::init(args.log_file.as_deref(), args.log_file_append);
|
||||
|
||||
// Read the trace file
|
||||
let pin_trace = {
|
||||
let mut pin_trace_file = fs::File::open(&args.trace_file).context("Unable to open trace file")?;
|
||||
PinTrace::from_reader(&mut pin_trace_file).context("Unable to parse pin trace")?
|
||||
};
|
||||
tracing::trace!(target: "ftmemsim::parse_pin_trace", ?pin_trace, "Parsed pin trace");
|
||||
let mut pin_trace_file = fs::File::open(&args.trace_file).context("Unable to open trace file")?;
|
||||
let mut pin_trace_reader = PinTraceReader::from_reader(&mut pin_trace_file).context("Unable to parse pin trace")?;
|
||||
tracing::trace!(target: "ftmemsim::parse_pin_trace", ?pin_trace_reader, "Parsed pin trace");
|
||||
|
||||
// Run the simulator
|
||||
let mut sim = Simulator::new(0, Duration::from_secs_f64(0.1));
|
||||
@@ -44,12 +42,12 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
global_cooling_threshold: 18,
|
||||
},
|
||||
vec![
|
||||
hemem::Memory::new("ram", 100, hemem::memories::AccessLatencies {
|
||||
hemem::Memory::new("ram", 100 * 100, hemem::memories::AccessLatencies {
|
||||
read: FemtoDuration::from_nanos_f64(1.5),
|
||||
write: FemtoDuration::from_nanos_f64(1.0),
|
||||
fault: FemtoDuration::from_nanos_f64(10.0),
|
||||
}),
|
||||
hemem::Memory::new("optane", 800, hemem::memories::AccessLatencies {
|
||||
hemem::Memory::new("optane", 800 * 100, hemem::memories::AccessLatencies {
|
||||
read: FemtoDuration::from_nanos_f64(5.0),
|
||||
write: FemtoDuration::from_nanos_f64(4.0),
|
||||
fault: FemtoDuration::from_nanos_f64(50.0),
|
||||
@@ -57,7 +55,7 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
],
|
||||
);
|
||||
|
||||
sim.run(pin_trace.records.iter().copied(), &mut hemem)
|
||||
sim.run(&mut pin_trace_reader, &mut hemem)
|
||||
.context("Unable to run simulator")?;
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -8,22 +8,25 @@ use {
|
||||
std::io,
|
||||
};
|
||||
|
||||
/// Pin trace
|
||||
/// Pin trace reader
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PinTrace {
|
||||
pub struct PinTraceReader<R> {
|
||||
/// Header
|
||||
pub header: Header,
|
||||
_header: Header,
|
||||
|
||||
/// All records
|
||||
pub records: Vec<Record>,
|
||||
/// Records remaining
|
||||
records_remaining: u64,
|
||||
|
||||
/// Reader
|
||||
reader: R,
|
||||
}
|
||||
|
||||
impl PinTrace {
|
||||
impl<R: io::Read + io::Seek> PinTraceReader<R> {
|
||||
/// Magic
|
||||
pub const MAGIC: [u8; 8] = *b"PINT v0\0";
|
||||
|
||||
/// Parses a pin trace from a reader
|
||||
pub fn from_reader<R: io::Read + io::Seek>(reader: &mut R) -> Result<Self, anyhow::Error> {
|
||||
pub fn from_reader(mut reader: R) -> Result<Self, anyhow::Error> {
|
||||
// Read the magic
|
||||
let magic = reader.read_byte_array().context("Unable to read magic")?;
|
||||
anyhow::ensure!(
|
||||
@@ -34,10 +37,11 @@ impl PinTrace {
|
||||
);
|
||||
|
||||
// Read the header
|
||||
let header = Header::from_reader(reader).context("Unable to read header")?;
|
||||
let header = Header::from_reader(&mut reader).context("Unable to read header")?;
|
||||
tracing::trace!(?header, "Parsed header");
|
||||
|
||||
// Get the total number of records
|
||||
// TODO: Not have this hack here?
|
||||
let total_records = {
|
||||
let magic_size = Self::MAGIC.len() as u64;
|
||||
let header_size = Header::BYTE_SIZE as u64;
|
||||
@@ -55,14 +59,30 @@ impl PinTrace {
|
||||
(total_actual_size - magic_size - header_size) / record_size
|
||||
};
|
||||
|
||||
let mut records =
|
||||
Vec::with_capacity(usize::try_from(total_records).context("Total records didn't fit into a `usize`")?);
|
||||
for record_idx in 0..total_records {
|
||||
let record = Record::from_reader(reader).with_context(|| format!("Unable to read record {record_idx}"))?;
|
||||
records.push(record);
|
||||
Ok(Self {
|
||||
_header: header,
|
||||
records_remaining: total_records,
|
||||
reader,
|
||||
})
|
||||
}
|
||||
|
||||
/// Reads the next record
|
||||
pub fn read_next(&mut self) -> Result<Option<Record>, anyhow::Error> {
|
||||
// If we're done, return `None`
|
||||
if self.records_remaining == 0 {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
Ok(Self { header, records })
|
||||
// Else parse the next record and reduce the remaining records
|
||||
let record = Record::from_reader(&mut self.reader).context("Unable to read record")?;
|
||||
self.records_remaining -= 1;
|
||||
|
||||
Ok(Some(record))
|
||||
}
|
||||
|
||||
/// Returns the remaining records
|
||||
pub fn records_remaining(&self) -> u64 {
|
||||
self.records_remaining
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
21
src/sim.rs
21
src/sim.rs
@@ -2,10 +2,11 @@
|
||||
|
||||
// Imports
|
||||
use {
|
||||
crate::{pin_trace, util},
|
||||
crate::{pin_trace, pin_trace::PinTraceReader, util},
|
||||
anyhow::Context,
|
||||
std::{
|
||||
fmt,
|
||||
io,
|
||||
time::{Duration, Instant},
|
||||
},
|
||||
};
|
||||
@@ -35,17 +36,23 @@ impl Simulator {
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs the simulator on records `records` with classifier `classifier`
|
||||
/// Runs the simulator on all traces from `pin_trace_reader` with classifier `classifier`
|
||||
pub fn run<C: Classifier>(
|
||||
&mut self,
|
||||
records: impl IntoIterator<Item = pin_trace::Record>,
|
||||
pin_trace_reader: &mut PinTraceReader<impl io::Read + io::Seek>,
|
||||
classifier: &mut C,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
// Note: We start in the past so that we output right away at the start
|
||||
let mut last_debug_time = Instant::now() - self.debug_output_freq;
|
||||
|
||||
// Create the record iterator
|
||||
let total_records = pin_trace_reader.records_remaining();
|
||||
let record_it = std::iter::from_fn(|| pin_trace_reader.read_next().transpose());
|
||||
|
||||
// Go through all records
|
||||
for record in records.into_iter().step_by(self.trace_skip + 1) {
|
||||
for (record_idx, record_res) in record_it.enumerate().step_by(self.trace_skip + 1) {
|
||||
let record = record_res.context("Unable to read next record")?;
|
||||
|
||||
// Handle each trace
|
||||
let trace = Trace { record };
|
||||
classifier
|
||||
@@ -55,7 +62,11 @@ impl Simulator {
|
||||
// Then show debug output, if it's been long enough
|
||||
let cur_time = Instant::now();
|
||||
if cur_time.duration_since(last_debug_time) >= self.debug_output_freq {
|
||||
tracing::info!("Debug: {}", util::DisplayWrapper::new(|f| classifier.fmt_debug(f)));
|
||||
let records_processed_percentage = 100.0 * (record_idx as f64 / total_records as f64);
|
||||
tracing::info!(
|
||||
"[{records_processed_percentage:.2}%] Debug: {}",
|
||||
util::DisplayWrapper::new(|f| classifier.fmt_debug(f))
|
||||
);
|
||||
last_debug_time = cur_time
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user