soothfast_report/
perf_table.rs1use serde_json::Value;
5
6pub struct Row {
8 pub id: String,
9 pub instructions: Option<u64>,
10 pub median_ns: Option<f64>,
11 pub p99_ns: Option<f64>,
12 pub allocs: Option<u64>,
13 pub polls: Option<u64>,
14}
15
16pub fn rows(baseline: &Value) -> Vec<Row> {
18 let Some(items) = baseline["items"].as_object() else {
19 return Vec::new();
20 };
21 items
22 .iter()
23 .map(|(id, m)| Row {
24 id: id.clone(),
25 instructions: m["perfcnt"]["instructions"].as_u64(),
26 median_ns: m["walltime"]["median_ns"].as_f64(),
27 p99_ns: m["walltime"]["p99_ns"].as_f64(),
28 allocs: m["alloc"]["allocs"].as_u64(),
29 polls: m["asyncexec"]["polls"].as_u64(),
30 })
31 .collect()
32}
33
34fn fmt_u(v: Option<u64>) -> String {
35 v.map(|x| x.to_string()).unwrap_or_else(|| "n/a".into())
36}
37fn fmt_ns(v: Option<f64>) -> String {
38 match v {
39 Some(ns) if ns >= 1e6 => format!("{:.2}ms", ns / 1e6),
40 Some(ns) if ns >= 1e3 => format!("{:.2}µs", ns / 1e3),
41 Some(ns) => format!("{ns:.1}ns"),
42 None => "n/a".into(),
43 }
44}
45
46pub fn markdown(baseline: &Value) -> String {
48 let mut out = String::from(
49 "| item | instructions | median | p99 | allocs | polls |\n|---|---:|---:|---:|---:|---:|\n",
50 );
51 for r in rows(baseline) {
52 out.push_str(&format!(
53 "| `{}` | {} | {} | {} | {} | {} |\n",
54 r.id,
55 fmt_u(r.instructions),
56 fmt_ns(r.median_ns),
57 fmt_ns(r.p99_ns),
58 fmt_u(r.allocs),
59 fmt_u(r.polls),
60 ));
61 }
62 out
63}
64
65pub fn html(baseline: &Value) -> String {
67 let mut out = String::from(
68 "<table>\n<thead><tr><th>item</th><th>instructions</th><th>median</th><th>p99</th><th>allocs</th><th>polls</th></tr></thead>\n<tbody>\n",
69 );
70 for r in rows(baseline) {
71 out.push_str(&format!(
72 "<tr><td><code>{}</code></td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>\n",
73 r.id,
74 fmt_u(r.instructions),
75 fmt_ns(r.median_ns),
76 fmt_ns(r.p99_ns),
77 fmt_u(r.allocs),
78 fmt_u(r.polls),
79 ));
80 }
81 out.push_str("</tbody>\n</table>\n");
82 out
83}
84
85#[cfg(test)]
86mod tests {
87 use serde_json::json;
88
89 #[test]
90 fn renders_markdown_rows() {
91 let baseline = json!({ "items": { "demo::f": {
92 "perfcnt": { "instructions": 98 },
93 "walltime": { "median_ns": 13.7, "p99_ns": 15.0 },
94 "alloc": { "allocs": 0, "bytes": 0 }
95 }}});
96 let md = super::markdown(&baseline);
97 assert!(md.contains("| `demo::f` | 98 | 13.7ns | 15.0ns | 0 | n/a |"));
98 }
99}