1use anyhow::Result;
3use chrono::prelude::*;
4use serde::{Deserialize, Serialize};
5use std::time::SystemTime;
6
7use rd_util::*;
8
9pub const BENCH_FILENAME: &str = "bench.json";
10
11const BENCH_DOC: &str = "\
12//
13// rd-agent benchmark results
14//
15// timestamp: When this report was generated
16// hashd_seq: Current rd-hashd bench result sequence, see cmd.json
17// iocost_seq: Current iocost bench result sequence, see cmd.json
18// hashd[].hash_size: Mean hash size which determines CPU usage
19// hashd[].rps_max: Maximum RPS
20// hashd[].mem_size: Memory size base
21// hashd[].mem_frac: Memory size is mem_size * mem_frac, tune this if needed
22// hashd[].chunk_pages: Memory access chunk size in pages
23// hashd[].fake_cpu_load: Bench was run with --bench-fake-cpu-load
24// iocost.devnr: Storage device devnr
25// iocost.model: Model parameters
26// iocost.qos: QoS parameters
27//
28";
29
30#[derive(Clone, Debug, Default, Serialize, Deserialize)]
31#[serde(default)]
32pub struct HashdKnobs {
33 pub hash_size: usize,
34 pub rps_max: u32,
35 pub mem_size: u64,
36 pub mem_frac: f64,
37 pub chunk_pages: usize,
38 pub fake_cpu_load: bool,
39}
40
41impl std::fmt::Display for HashdKnobs {
42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 write!(
44 f,
45 "hash_size={} rps_max={} mem_actual={} chunk_pages={}{}",
46 format_size(self.hash_size),
47 self.rps_max,
48 format_size(self.actual_mem_size()),
49 self.chunk_pages,
50 if self.fake_cpu_load {
51 " fake_cpu_load"
52 } else {
53 ""
54 }
55 )
56 }
57}
58
59impl HashdKnobs {
60 pub fn actual_mem_size(&self) -> u64 {
61 (self.mem_size as f64 * self.mem_frac).ceil() as u64
62 }
63}
64
65#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
66pub struct IoCostKnobs {
67 pub devnr: String,
68 pub model: IoCostModelParams,
69 pub qos: IoCostQoSParams,
70}
71
72#[derive(Clone, Debug, Serialize, Deserialize)]
73pub struct BenchKnobs {
74 pub timestamp: DateTime<Local>,
75 pub hashd_seq: u64,
76 pub iocost_seq: u64,
77 pub hashd: HashdKnobs,
78 pub iocost: IoCostKnobs,
79 pub iocost_dev_model: String,
80 pub iocost_dev_fwrev: String,
81 pub iocost_dev_size: u64,
82}
83
84impl Default for BenchKnobs {
85 fn default() -> Self {
86 Self {
87 timestamp: DateTime::from(SystemTime::now()),
88 hashd_seq: 0,
89 iocost_seq: 0,
90 hashd: Default::default(),
91 iocost: Default::default(),
92 iocost_dev_model: String::new(),
93 iocost_dev_fwrev: String::new(),
94 iocost_dev_size: 0,
95 }
96 }
97}
98
99impl JsonLoad for BenchKnobs {
100 fn loaded(&mut self, _prev: Option<&mut Self>) -> Result<()> {
101 self.iocost.qos.sanitize();
102 Ok(())
103 }
104}
105
106impl JsonSave for BenchKnobs {
107 fn preamble() -> Option<String> {
108 Some(BENCH_DOC.to_string())
109 }
110}