Replaced plotlib with gnuplot.

This commit is contained in:
Filipe Rodrigues 2023-05-25 02:15:38 +01:00
parent dc67a9c9e1
commit d193e28549
6 changed files with 127 additions and 252 deletions

146
Cargo.lock generated
View File

@ -2,21 +2,6 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "anstream"
version = "0.3.2"
@ -89,21 +74,6 @@ dependencies = [
"num-traits",
]
[[package]]
name = "backtrace"
version = "0.3.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "bitflags"
version = "1.3.2"
@ -161,7 +131,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.16",
"syn",
]
[[package]]
@ -220,29 +190,7 @@ checksum = "311a6d2f1f9d60bff73d2c78a0af97ed27f79672f15c238192a5bbb64db56d00"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
]
[[package]]
name = "failure"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
dependencies = [
"backtrace",
"failure_derive",
]
[[package]]
name = "failure_derive"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
"synstructure",
"syn",
]
[[package]]
@ -274,8 +222,8 @@ dependencies = [
"anyhow",
"clap",
"ftmemsim-util",
"gnuplot",
"itertools",
"plotlib",
"serde_json",
"tracing",
]
@ -292,10 +240,13 @@ dependencies = [
]
[[package]]
name = "gimli"
version = "0.27.2"
name = "gnuplot"
version = "0.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
checksum = "c3980f1547c7c19b51b5a89fbc6b8913a7d441c7f017547d5b40079ba7ca0321"
dependencies = [
"byteorder",
]
[[package]]
name = "heck"
@ -389,21 +340,6 @@ dependencies = [
"regex-automata",
]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "miniz_oxide"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
dependencies = [
"adler",
]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
@ -424,15 +360,6 @@ dependencies = [
"libm",
]
[[package]]
name = "object"
version = "0.30.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.17.1"
@ -451,16 +378,6 @@ version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
[[package]]
name = "plotlib"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9462104f987d8d0f6625f0c7764f1c8b890bd1dc8584d8293e031f25c5a0d242"
dependencies = [
"failure",
"svg",
]
[[package]]
name = "proc-macro2"
version = "1.0.57"
@ -509,12 +426,6 @@ version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
[[package]]
name = "rustc-demangle"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "rustix"
version = "0.37.19"
@ -552,7 +463,7 @@ checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn",
]
[[package]]
@ -587,23 +498,6 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "svg"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3685c82a045a6af0c488f0550b0f52b4c77d2a52b0ca8aba719f9d268fa96965"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.16"
@ -615,18 +509,6 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "synstructure"
version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
"unicode-xid",
]
[[package]]
name = "thread_local"
version = "1.1.7"
@ -657,7 +539,7 @@ checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
"syn",
]
[[package]]
@ -705,12 +587,6 @@ version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
[[package]]
name = "unicode-xid"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "utf8parse"
version = "0.2.1"

View File

@ -16,7 +16,7 @@ tracing = "0.1.37"
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
serde = { version = "1.0.163", features = ["derive"] }
serde_json = "1.0.96"
plotlib = "0.5.1"
gnuplot = "0.0.38"
# Workspace members
ftmemsim = { path = "ftmemsim" }

View File

@ -7,8 +7,8 @@ edition = "2021"
clap = { workspace = true }
tracing = { workspace = true }
plotlib = { workspace = true }
anyhow = { workspace = true }
serde_json = { workspace = true }
itertools = { workspace = true }
gnuplot = { workspace = true }
ftmemsim-util = { workspace = true }

View File

@ -36,32 +36,8 @@ pub enum SubCmd {
input_file: PathBuf,
/// Output
#[clap(short = 'o', long = "output")]
output_file: PathBuf,
/// Point size
#[clap(long = "point-size", default_value_t = 1.0)]
point_size: f32,
/// Width
#[clap(long = "width", default_value_t = 640)]
width: u32,
/// Height
#[clap(long = "height", default_value_t = 480)]
height: u32,
/// Tick marks for x axis
#[clap(long = "x-tick-marks", default_value_t = 6)]
x_tick_marks: usize,
/// Tick marks for y axis
#[clap(long = "y-tick-marks", default_value_t = 6)]
y_tick_marks: usize,
/// Point color
#[clap(long = "point-color", default_value_t = { "#000000".to_owned() })]
point_color: String,
#[clap(flatten)]
output: ArgsOutputFile,
},
/// Creates a histogram of page migrations
@ -73,8 +49,8 @@ pub enum SubCmd {
input_file: PathBuf,
/// Output
#[clap(short = 'o', long = "output")]
output_file: PathBuf,
#[clap(flatten)]
output: ArgsOutputFile,
},
/// Page temperature
@ -86,7 +62,23 @@ pub enum SubCmd {
input_file: PathBuf,
/// Output
#[clap(short = 'o', long = "output")]
output_file: PathBuf,
#[clap(flatten)]
output: ArgsOutputFile,
},
}
/// Output file
#[derive(Debug, clap::Args)]
pub struct ArgsOutputFile {
/// Output file
#[clap(short = 'o', long = "output")]
pub file: PathBuf,
/// Output file width
#[clap(long = "output-width", default_value_t = 640)]
pub width: u32,
/// Output file height
#[clap(long = "output-height", default_value_t = 480)]
pub height: u32,
}

View File

@ -3,8 +3,6 @@
// Features
#![feature(lint_reasons)]
use plotlib::style::{LineJoin, LineStyle};
// Modules
mod args;
@ -14,13 +12,9 @@ use {
args::Args,
clap::Parser,
ftmemsim_util::logger,
gnuplot::{AxesCommon, PlotOption},
itertools::Itertools,
plotlib::{
page::Page,
repr::{Histogram, HistogramBins, Plot},
style::{BoxStyle, PointStyle},
view::ContinuousView,
},
std::{collections::BTreeMap, path::Path},
};
fn main() -> Result<(), anyhow::Error> {
@ -33,16 +27,7 @@ fn main() -> Result<(), anyhow::Error> {
// Then check the sub-command
match args.sub_cmd {
args::SubCmd::PageLocations {
input_file,
output_file,
point_size,
width,
height,
x_tick_marks,
y_tick_marks,
point_color,
} => {
args::SubCmd::PageLocations { input_file, output } => {
// Parse the page locations
let page_locations = {
let page_locations_file = std::fs::File::open(input_file).context("Unable to open input file")?;
@ -74,40 +59,36 @@ fn main() -> Result<(), anyhow::Error> {
.unwrap_or((0, 1));
// And calculate the points to display
let points = page_locations
let (points_x, points_y) = page_locations
.locations
.iter()
.flat_map(|(page_ptr, page_locations)| {
page_locations.iter().map(|page_location| {
(
(page_location.time - min_time) as f64 / (max_time - min_time) as f64,
*page_ptr_idxs.get(page_ptr).expect("Page ptr had no index") as f64,
*page_ptr_idxs.get(page_ptr).expect("Page ptr had no index"),
)
})
})
.collect::<Vec<_>>();
.unzip::<_, _, Vec<_>, Vec<_>>();
// Finally build the plot and render it
let plot = Plot::new(points).point_style(PointStyle::new().size(point_size).colour(point_color));
// Finally create and save the plot
let mut fg = gnuplot::Figure::new();
fg.axes2d()
.points(&points_x, &points_y, &[
PlotOption::Caption("Page locations"),
PlotOption::Color("black"),
PlotOption::PointSymbol('.'),
PlotOption::PointSize(1.0),
])
.set_x_label("Time (normalized)", &[])
.set_y_label("Page (indexed)", &[]);
let view = ContinuousView::new()
.add(plot)
.x_max_ticks(x_tick_marks)
.y_max_ticks(y_tick_marks)
.x_label("Time")
.y_label("Page (Indexed)");
Page::single(&view)
.dimensions(width, height)
.save(output_file)
.map_err(|err| anyhow::anyhow!("Unable to save output file: {err:?}"))?;
self::save_plot(&output.file, &mut fg, output.width, output.height).context("Unable to save plot")?;
},
// TODO: Allow customization for all of the parameters here?
args::SubCmd::PageMigrations {
input_file,
output_file,
} => {
args::SubCmd::PageMigrations { input_file, output } => {
// Parse the page locations
let page_locations = {
let page_locations_file = std::fs::File::open(input_file).context("Unable to open input file")?;
@ -115,40 +96,30 @@ fn main() -> Result<(), anyhow::Error> {
.context("Unable to parse input file")?
};
let max_migrations = page_locations
.locations
.values()
.map(|page_locations| page_locations.len())
.max()
.unwrap_or(0);
// Build the data
let data = page_locations
.locations
.values()
.map(|page_locations| page_locations.len() as f64)
.collect::<Vec<_>>();
.map(|page_locations| page_locations.len())
.counts()
.into_iter()
.collect::<BTreeMap<_, _>>();
// Finally build the histogram and render it
let hist = Histogram::from_slice(&data, HistogramBins::Count(20.min(max_migrations) - 1))
.style(&BoxStyle::new().fill("burlywood"));
// Finally create and save the plot
let mut fg = gnuplot::Figure::new();
fg.axes2d()
.boxes_set_width(data.keys(), data.values(), (0..data.len()).map(|_| 0.8), &[
PlotOption::Caption("Migration count"),
PlotOption::Color("black"),
])
.set_y_log(Some(10.0))
.set_x_ticks(Some((gnuplot::AutoOption::Fix(1.0), 0)), &[], &[])
.set_x_label("Migrations", &[])
.set_y_label("Count", &[]);
let view = ContinuousView::new()
.add(hist)
.x_max_ticks(20.min(max_migrations))
.y_max_ticks(6)
.x_label("Migrations")
.y_label("Occurrences");
Page::single(&view)
.dimensions(640, 480)
.save(output_file)
.map_err(|err| anyhow::anyhow!("Unable to save output file: {err:?}"))?;
self::save_plot(&output.file, &mut fg, output.width, output.height).context("Unable to save plot")?;
},
args::SubCmd::PageTemperature {
input_file,
output_file,
} => {
args::SubCmd::PageTemperature { input_file, output } => {
// Parse the page accesses
let page_accesses = {
let page_accesses_file = std::fs::File::open(input_file).context("Unable to open input file")?;
@ -165,7 +136,7 @@ fn main() -> Result<(), anyhow::Error> {
.unwrap_or((0, 1));
let mut temp_cur_average = 0.0;
let temp_points = page_accesses
let (points_x, points_y) = page_accesses
.accesses
.iter()
.enumerate()
@ -176,25 +147,51 @@ fn main() -> Result<(), anyhow::Error> {
temp_cur_average / (idx as f64 + 1.0),
)
})
.collect::<Vec<_>>();
.unzip::<_, _, Vec<_>, Vec<_>>();
// Finally build the plot and render it
let temp_plot = Plot::new(temp_points)
.line_style(LineStyle::new().width(1.0).colour("#000000").linejoin(LineJoin::Round));
// Finally create and save the plot
let mut fg = gnuplot::Figure::new();
fg.axes2d()
.lines(&points_x, &points_y, &[
PlotOption::Caption("Page locations"),
PlotOption::Color("black"),
PlotOption::PointSymbol('.'),
PlotOption::PointSize(1.0),
])
.set_x_label("Time (normalized)", &[])
.set_y_label("Page (indexed)", &[]);
let view = ContinuousView::new()
.add(temp_plot)
.x_max_ticks(6)
.y_max_ticks(6)
.x_label("Time")
.y_label("Temperature");
Page::single(&view)
.dimensions(640, 480)
.save(output_file)
.map_err(|err| anyhow::anyhow!("Unable to save output file: {err:?}"))?;
self::save_plot(&output.file, &mut fg, output.width, output.height).context("Unable to save plot")?;
},
}
Ok(())
}
/// Saves the plot `fg` to `output_file`, depending on it's extension
fn save_plot(output_file: &Path, fg: &mut gnuplot::Figure, width_px: u32, height_px: u32) -> Result<(), anyhow::Error> {
match output_file
.extension()
.context("Output file had no extension")?
.to_str()
.context("Output file extension was non-utf8")?
.to_ascii_lowercase()
.as_str()
{
"png" => fg
.save_to_png(output_file, width_px, height_px)
.context("Unable to save output file as png")?,
"svg" => fg
.save_to_svg(output_file, width_px, height_px)
.context("Unable to save output file as svg")?,
"html" => fg
.save_to_canvas(output_file, width_px, height_px)
.context("Unable to save output file as html canvas")?,
ext => anyhow::bail!("Unknown extension: {ext:?}"),
}
Ok(())
}

18
run.sh
View File

@ -9,11 +9,15 @@ PROFILE="dev"
#PROFILE="release"
#TRACE_FILE="resources/traces/bfs.g5.n5.trace"
TRACE_FILE="resources/traces/bfs.g17.n100.t1.trace"
TRACE_FILE="resources/traces/bfs.g15.n15.trace"
#TRACE_FILE="resources/traces/bfs.g17.n100.t1.trace"
#TRACE_FILE="resources/traces/bc.g18.n100.t1.trace"
CONFIG="config.json"
OUTPUT_WIDTH="1000"
OUTPUT_HEIGHT="1000"
rm -rf "$LOG_FILE"
echo "Simulating"
@ -29,18 +33,24 @@ cargo run --profile "$PROFILE" -p ftmemsim-graphs -- \
--log-file "$LOG_FILE" \
page-locations \
"resources/data/page_locations.json" \
--output "resources/data/page_locations.svg"
--output "resources/data/page_locations.png" \
--output-width "$OUTPUT_WIDTH" \
--output-height "$OUTPUT_HEIGHT"
cargo run --profile "$PROFILE" -p ftmemsim-graphs -- \
--log-file-append \
--log-file "$LOG_FILE" \
page-migrations \
"resources/data/page_locations.json" \
--output "resources/data/page_migrations.svg"
--output "resources/data/page_migrations.png" \
--output-width "$OUTPUT_WIDTH" \
--output-height "$OUTPUT_HEIGHT"
cargo run --profile "$PROFILE" -p ftmemsim-graphs -- \
--log-file-append \
--log-file "$LOG_FILE" \
page-temperature \
"resources/data/page_accesses.json" \
--output "resources/data/page_temperature.svg"
--output "resources/data/page_temperature.png" \
--output-width "$OUTPUT_WIDTH" \
--output-height "$OUTPUT_HEIGHT"