1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use {
crate::*,
serde::{Serialize, Deserialize},
};
/// A whole benchmark.
///
/// You normally create it with the `glassbench!`
/// macro which will manage table rendering, saving
/// and graphing if required by arguments.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GlassBench {
pub id: String,
pub git_info: Option<GitInfo>,
pub name: String,
pub tasks: Vec<TaskBench>,
}
impl GlassBench {
/// Create a benchmark with a specific id
/// and name.
///
/// You normally create it with the `glassbench!`
/// macro which will fetch the id in the name of
/// the executed benchmark.
pub fn new<S1, S2>(id: S1, name: S2) -> Self
where
S1: Into<String>,
S2: Into<String>,
{
Self {
id: id.into(),
name: name.into(),
tasks: Vec::new(),
git_info: GitInfo::read(),
}
}
/// Specify a task to benchmark.
pub fn task<S: Into<String>, F>(&mut self, name: S, mut f: F)
where
F: FnMut(&mut TaskBench),
{
let mut b = TaskBench::new(name.into());
f(&mut b);
self.tasks.push(b);
}
/// print the report to the console.
///
/// You don't have to call this yourself if you use
/// the `glassbench!` macro.
pub fn print_report(&self) {
let previous = match DatedGlassbench::last(&self.id) {
Err(e) => {
eprintln!("failed loading previous report: {}", e);
None
}
Ok(previous) => {
previous
}
};
let report = Report::new(&self, &previous);
report.print();
}
/// graph some history.
///
/// You don't have to call this yourself if you use
/// the `glassbench!` macro.
pub fn graph(&self, graph_arg: &str) {
if let Ok(num) = graph_arg.parse::<usize>() {
if num == 0 {
eprintln!("graph argument 0 not yet implemented");
} else if let Some(task) = self.tasks.get(num-1) {
match History::of_task(&self.id, &task.name) {
Ok(history) if history.is_graphable() => {
match history.open_graph() {
Err(e) => {
eprintln!("Error opening history graph: {}", e);
}
_ => {
println!("History graph open in your browser");
}
}
}
Err(e) => {
eprintln!("reading task history failed: {}", e);
}
_ => {
eprintln!("not enough points in history");
}
}
} else {
eprintln!("no task with number {} found", num);
}
} else {
eprintln!("graph argument not understood: {:?}", graph_arg);
}
}
/// save the measurements into the .glassbench directory
///
/// You don't have to call this yourself if you use
/// the `glassbench!` macro.
pub fn save(self) {
let dgb = DatedGlassbench::new(self);
dgb.save();
}
}