Separated page_migrations graph into it's own function.

This commit is contained in:
Filipe Rodrigues 2023-06-06 03:31:22 +01:00
parent a27a8d394a
commit 6ed293c165

View File

@ -33,128 +33,7 @@ fn main() -> Result<(), anyhow::Error> {
// Then check the sub-command
match args.sub_cmd {
args::SubCmd::PageMigrations(cmd_args) => {
// Parse the config
// TODO: Use config
let config = self::read_config(&cmd_args.config_file)
.with_context(|| format!("Unable to read config file: {:?}", cmd_args.config_file))?;
// Parse the input file
let data = self::read_data(&cmd_args.input_file)
.with_context(|| format!("Unable to read data file: {:?}", cmd_args.input_file))?;
// Then index the page pointers.
// Note: We do this because the page pointers are very far away, value-wise, which
// causes them to display far away in the graph. Since the actual values of the
// pages don't matter to us, we just index them by order of appearance.
let page_ptr_idxs = data
.hemem
.page_migrations
.migrations
.iter()
.enumerate()
.map(|(idx, (page_ptr, _))| (page_ptr, idx))
.collect::<std::collections::HashMap<_, _>>();
// Then calculate the min/max time so we can normalize it to 0..1.
// Note: We do this because the time values themselves don't matter, only
// the relative time.
// TODO: Better defaults when empty?
let (min_time, max_time) = data
.hemem
.page_migrations
.migrations
.iter()
.flat_map(|(_, page_migrations)| page_migrations.iter().map(|page_migration| page_migration.time))
.minmax()
.into_option()
.unwrap_or((0, 1));
// And calculate the points to display
struct Point {
x: f64,
y: usize,
}
// Note: We use `BTreeMap` here to ensure a consistent order across runs (for creating gifs)
let mut points_alloc = vec![];
let mut points_migrations_all = BTreeMap::<(usize, usize), Vec<Point>>::new();
for (page_ptr, page_migrations) in &data.hemem.page_migrations.migrations {
for page_migration in page_migrations {
// Get the points to add the point to.
// Note: If we didn't have a previous memory index, we use the allocations bucket, else
// we grab corresponding to the `(prev, cur)` migration pair
let points = match page_migration.prev_mem_idx {
Some(prev_mem_idx) => points_migrations_all
.entry((prev_mem_idx, page_migration.cur_mem_idx))
.or_default(),
None => &mut points_alloc,
};
points.push(Point {
x: (page_migration.time - min_time) as f64 / (max_time - min_time) as f64,
y: *page_ptr_idxs.get(page_ptr).expect("Page ptr had no index"),
});
}
}
// Finally create and save the plot
let mut fg = gnuplot::Figure::new();
let fg_axes2d = fg
.axes2d()
.points(points_alloc.iter().map(|p| p.x), points_alloc.iter().map(|p| p.y), &[
PlotOption::Caption("Page allocations"),
PlotOption::Color("blue"),
PlotOption::PointSymbol('O'),
PlotOption::PointSize(2.0 * cmd_args.point_size),
]);
for ((prev_mem_idx, cur_mem_idx), points_migrations) in points_migrations_all {
// Calculate the color for these migrations
// Note: We use the red to dictate the current memory and green for the previous,
// this is to a greener color indicates a positive migration, while a redder
// color a negative migration
let max_mem_idx = config.hemem.memories.len();
let color = LinSrgb::new(
cur_mem_idx as f64 / max_mem_idx as f64,
prev_mem_idx as f64 / max_mem_idx as f64,
0.0,
);
let color = format!("#{:x}", color.into_format::<u8>());
// Then get the memories (for then ames)
let prev_mem = config
.hemem
.memories
.get(prev_mem_idx)
.context("Config had less memories than input file")?;
let cur_mem = config
.hemem
.memories
.get(cur_mem_idx)
.context("Config had less memories than input file")?;
fg_axes2d.points(
points_migrations.iter().map(|p| p.x),
points_migrations.iter().map(|p| p.y),
&[
PlotOption::Caption(&format!("Page migrations ({} to {})", prev_mem.name, cur_mem.name)),
PlotOption::Color(&color),
PlotOption::PointSymbol('O'),
PlotOption::PointSize(cmd_args.point_size),
],
);
}
fg_axes2d
.set_x_label("Time (normalized)", &[])
.set_y_label("Page (indexed)", &[])
.set_x_range(AutoOption::Fix(0.0), AutoOption::Fix(1.0))
.set_y_range(AutoOption::Fix(0.0), AutoOption::Fix(page_ptr_idxs.len() as f64));
// Then output the plot
self::handle_output(&cmd_args.output, &mut fg).context("Unable to handle output")?;
},
args::SubCmd::PageMigrations(cmd_args) => self::draw_page_migrations(&cmd_args)?,
// TODO: This is no longer a histogram, rename it?
args::SubCmd::PageMigrationsHist(cmd_args) => {
@ -412,6 +291,129 @@ fn main() -> Result<(), anyhow::Error> {
Ok(())
}
/// Draws the page migrations plot
fn draw_page_migrations(cmd_args: &args::PageMigrations) -> Result<(), anyhow::Error> {
// Parse the config and input file
let config = self::read_config(&cmd_args.config_file)
.with_context(|| format!("Unable to read config file: {:?}", cmd_args.config_file))?;
let data = self::read_data(&cmd_args.input_file)
.with_context(|| format!("Unable to read data file: {:?}", cmd_args.input_file))?;
// Then index the page pointers.
// Note: We do this because the page pointers are very far away, value-wise, which
// causes them to display far away in the graph. Since the actual values of the
// pages don't matter to us, we just index them by order of appearance.
let page_ptr_idxs = data
.hemem
.page_migrations
.migrations
.iter()
.enumerate()
.map(|(idx, (page_ptr, _))| (page_ptr, idx))
.collect::<std::collections::HashMap<_, _>>();
// Then calculate the min/max time so we can normalize it to 0..1.
// Note: We do this because the time values themselves don't matter, only
// the relative time.
// TODO: Better defaults when empty?
let (min_time, max_time) = data
.hemem
.page_migrations
.migrations
.iter()
.flat_map(|(_, page_migrations)| page_migrations.iter().map(|page_migration| page_migration.time))
.minmax()
.into_option()
.unwrap_or((0, 1));
// And calculate the points to display
struct Point {
x: f64,
y: usize,
}
// Note: We use `BTreeMap` here to ensure a consistent order across runs (for creating gifs)
let mut points_alloc = vec![];
let mut points_migrations_all = BTreeMap::<(usize, usize), Vec<Point>>::new();
for (page_ptr, page_migrations) in &data.hemem.page_migrations.migrations {
for page_migration in page_migrations {
// Get the points to add the point to.
// Note: If we didn't have a previous memory index, we use the allocations bucket, else
// we grab corresponding to the `(prev, cur)` migration pair
let points = match page_migration.prev_mem_idx {
Some(prev_mem_idx) => points_migrations_all
.entry((prev_mem_idx, page_migration.cur_mem_idx))
.or_default(),
None => &mut points_alloc,
};
points.push(Point {
x: (page_migration.time - min_time) as f64 / (max_time - min_time) as f64,
y: *page_ptr_idxs.get(page_ptr).expect("Page ptr had no index"),
});
}
}
// Finally create and save the plot
let mut fg = gnuplot::Figure::new();
let fg_axes2d = fg
.axes2d()
.points(points_alloc.iter().map(|p| p.x), points_alloc.iter().map(|p| p.y), &[
PlotOption::Caption("Page allocations"),
PlotOption::Color("blue"),
PlotOption::PointSymbol('O'),
PlotOption::PointSize(2.0 * cmd_args.point_size),
]);
for ((prev_mem_idx, cur_mem_idx), points_migrations) in points_migrations_all {
// Calculate the color for these migrations
// Note: We use the red to dictate the current memory and green for the previous,
// this is to a greener color indicates a positive migration, while a redder
// color a negative migration
let max_mem_idx = config.hemem.memories.len();
let color = LinSrgb::new(
cur_mem_idx as f64 / max_mem_idx as f64,
prev_mem_idx as f64 / max_mem_idx as f64,
0.0,
);
let color = format!("#{:x}", color.into_format::<u8>());
// Then get the memories (for then ames)
let prev_mem = config
.hemem
.memories
.get(prev_mem_idx)
.context("Config had less memories than input file")?;
let cur_mem = config
.hemem
.memories
.get(cur_mem_idx)
.context("Config had less memories than input file")?;
fg_axes2d.points(
points_migrations.iter().map(|p| p.x),
points_migrations.iter().map(|p| p.y),
&[
PlotOption::Caption(&format!("Page migrations ({} to {})", prev_mem.name, cur_mem.name)),
PlotOption::Color(&color),
PlotOption::PointSymbol('O'),
PlotOption::PointSize(cmd_args.point_size),
],
);
}
fg_axes2d
.set_x_label("Time (normalized)", &[])
.set_y_label("Page (indexed)", &[])
.set_x_range(AutoOption::Fix(0.0), AutoOption::Fix(1.0))
.set_y_range(AutoOption::Fix(0.0), AutoOption::Fix(page_ptr_idxs.len() as f64));
// Then output the plot
self::handle_output(&cmd_args.output, &mut fg).context("Unable to handle output")?;
Ok(())
}
/// Computes the data to use fr the `page-migrations-hist` graph
fn page_migrations_hist_data(data: &ftmemsim::data::Data) -> Vec<usize> {