summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2021-12-05 15:57:12 +0200
committerLars Wirzenius <liw@liw.fi>2021-12-05 15:57:12 +0200
commit0133bd6fb912d0138841cd8d2a6c878c674e0e81 (patch)
tree9f527dde73dd77c6a5dc734640b4f6552153f1d9 /src
parent55000324bb4d6434fa147ce4c835a2c8cc76b757 (diff)
downloadobnam-benchmark-0133bd6fb912d0138841cd8d2a6c878c674e0e81.tar.gz
refactor: use a "step" abstraction for running benchmarks
Sponsored-by: author
Diffstat (limited to 'src')
-rw-r--r--src/bin/obnam-benchmark.rs20
-rw-r--r--src/lib.rs63
2 files changed, 62 insertions, 21 deletions
diff --git a/src/bin/obnam-benchmark.rs b/src/bin/obnam-benchmark.rs
index 8b31a82..b76a7aa 100644
--- a/src/bin/obnam-benchmark.rs
+++ b/src/bin/obnam-benchmark.rs
@@ -43,25 +43,9 @@ struct Run {
impl Run {
fn run(&self) -> anyhow::Result<()> {
let spec = Specification::from_file(&self.spec)?;
-
- for benchmark in spec.benchmarks() {
- println!("benchmark {}", benchmark.name());
- println!("start obnam server with empty chunks dir");
- println!("create empty test data directory");
- for backup in benchmark.backups() {
- println!("make changes to test data");
- for change in backup.changes() {
- change.execute()?;
- }
- println!("run backup, measure time and chunks directory");
- }
- for _ in benchmark.backups() {
- println!("run restore, measure time")
- }
- println!("stop obnam server");
- println!("clean up test data directory");
+ for step in spec.steps() {
+ println!("{:?}", step);
}
-
Ok(())
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 1122ada..6e731c2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,6 +1,7 @@
use serde::{Deserialize, Serialize};
use std::fs::File;
use std::path::{Path, PathBuf};
+use std::collections::HashSet;
#[derive(Debug, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
@@ -10,6 +11,9 @@ pub struct Specification {
#[derive(Debug, thiserror::Error)]
pub enum SpecificationError {
+ #[error("Duplicate benchmark name {0}")]
+ DuplicateBenchmark(String),
+
#[error("Couldn't open {0}: {1}")]
Open(PathBuf, std::io::Error),
@@ -40,29 +44,72 @@ pub enum Change {
Rename(FileCount),
}
-#[derive(Debug, Serialize, Deserialize)]
+#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Create {
files: u64,
file_size: u64,
}
-#[derive(Debug, Serialize, Deserialize)]
+#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileCount {
files: u64,
}
+#[derive(Debug)]
+pub enum Step {
+ Start(String),
+ Stop(String),
+ MeasureChunks,
+ Create(Create),
+ Rename(FileCount),
+ Delete(FileCount),
+ Backup(usize),
+ Restore(usize),
+}
+
impl Specification {
pub fn from_file(filename: &Path) -> Result<Self, SpecificationError> {
let f = File::open(filename)
.map_err(|err| SpecificationError::Open(filename.to_path_buf(), err))?;
- let spec = serde_yaml::from_reader(f)
+ let spec: Specification = serde_yaml::from_reader(f)
.map_err(|err| SpecificationError::Yaml(filename.to_path_buf(), err))?;
+ spec.check()?;
Ok(spec)
}
+ fn check(&self) -> Result<(), SpecificationError> {
+ let mut names = HashSet::new();
+ for name in self.benchmarks().map(|b| b.name()) {
+ let name = name.to_string();
+ if names.contains(&name) {
+ return Err(SpecificationError::DuplicateBenchmark(name));
+ }
+ names.insert(name);
+ }
+ Ok(())
+ }
+
pub fn benchmarks(&self) -> impl Iterator<Item = &Benchmark> {
self.benchmarks.iter()
}
+
+ pub fn steps(&self) -> Vec<Step> {
+ let mut steps = vec![];
+ for b in self.benchmarks() {
+ steps.push(Step::Start(b.name().to_string()));
+ for (i, backup) in b.backups().enumerate() {
+ for change in backup.changes() {
+ steps.push(Step::from(change));
+ }
+ steps.push(Step::Backup(i));
+ }
+ for (i, _) in b.backups().enumerate() {
+ steps.push(Step::Restore(i));
+ }
+ steps.push(Step::Stop(b.name().to_string()));
+ }
+ steps
+ }
}
impl Benchmark {
@@ -91,3 +138,13 @@ impl Change {
Ok(())
}
}
+
+impl Step {
+ pub fn from(change: &Change) -> Self {
+ match change {
+ Change::Create(x) => Self::Create(x.clone()),
+ Change::Rename(x) => Self::Rename(x.clone()),
+ Change::Delete(x) => Self::Delete(x.clone()),
+ }
+ }
+}