rd_agent_intf/
cmd.rs

1// Copyright (c) Facebook, Inc. and its affiliates.
2use serde::{Deserialize, Serialize};
3use std::collections::BTreeMap;
4
5use rd_util::*;
6
7lazy_static::lazy_static! {
8    static ref CMD_DOC: String = {
9        format!("\
10//
11// rd-agent command file
12//
13// This file controls workloads and benchmarks. hashd benchmark should be run at
14// least once before other workloads can be started. Setting a bench sequence
15// higher than the current value in the bench.json file initiates the benchmark.
16// Setting it to a number equal to or lower than cancels if currently running.
17// While a benchmark is running, all other workloads are stopped.
18//
19// One or two rd-hashd instances are used as the latency sensitive primary
20// workloads. When both instances are active, between the two, resources are
21// distributed according to their relative weights.
22//
23// Any number of sysloads and sideloads can be used. The only difference between
24// sysloads and sideloads is that sysloads are run under system.slice without
25// further supervision while sideloads are run under sideload.slice under the
26// control of the sideloader which, among other things, enforces CPU headroom.
27//
28// Each sys/sideload must have a unique name. The actual workload is determined
29// by DEF_ID which points to an entry in sideload-defs.json file. Creating an
30// entry starts the workload. Removing stops it.
31//
32//  cmd_seq: Written to cmd-ack.json once the commands are accepted
33//  bench_hashd_seq: If > bench::hashd_seq, start benchmark; otherwise, cancel
34//  bench_hashd_balloon_size: Memory balloon size during hashd benchmark, default ${dfl_bench_balloon}
35//  bench_hashd_args: Extra arguments hashd benchmark
36//  bench_iocost_seq: If > bench::iocost_seq, start benchmark; otherwise, cancel
37//  sideloader.cpu_headroom: Sideload CPU headroom ratio [0.0, 1.0]
38//  hashd[].active: On/off
39//  hashd[].lat_target_pct: Latency target percentile
40//  hashd[].lat_target: Latency target, defaults to 0.1 meaning 100ms
41//  hashd[].rps_target_ratio: RPS target as a ratio of bench::hashd.rps_max,
42//                            if >> 1.0, no practical rps limit, default 0.5
43//  hashd[].mem_ratio: Memory footprint adj [0.0, 1.0], null to use bench result
44//  hashd[].file_ratio: Pagecache portion of memory [0.0, 1.0], default ${dfl_file_ratio}
45//  hashd[].file_max_ratio: Max file_ratio, requires hashd restart [0.0, 1.0], default ${dfl_file_max_ratio}
46//  hashd[].file_addr_stdev: Memory access stdev in ratio of mean, null to use ${dfl_file_addr_stdev}
47//  hashd[].anon_addr_stdev: Memory access stdev in ratio of mean, null to use ${dfl_anon_addr_stdev}
48//  hashd[].log_bps: IO write bandwidth, default ${dfl_log_bps}Mbps
49//  hashd[].weight: Relative weight between the two hashd instances
50//  sysloads{{}}: \"NAME\": \"DEF_ID\" pairs for active sysloads
51//  sideloads{{}}: \"NAME\": \"DEF_ID\" pairs for active sideloads
52//  swappiness: /proc/sys/vm/swappiness, null to leave as-is
53//  zswap_enabled: zswap enable flag, null to leave as-is
54//  balloon_ratio: Memory balloon size given as a ratio to total memory, default 0.0
55//
56",
57                dfl_bench_balloon = Cmd::default().bench_hashd_balloon_size,
58                dfl_file_ratio = rd_hashd_intf::Params::default().file_frac,
59                dfl_file_max_ratio = rd_hashd_intf::Args::default().file_max_frac,
60                dfl_file_addr_stdev = rd_hashd_intf::Params::default().file_addr_stdev_ratio,
61                dfl_anon_addr_stdev = rd_hashd_intf::Params::default().anon_addr_stdev_ratio,
62                dfl_log_bps = to_mb(rd_hashd_intf::Params::default().log_bps),
63        )
64    };
65}
66
67#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
68pub struct SideloaderCmd {
69    pub cpu_headroom: f64,
70}
71
72#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
73pub struct HashdCmd {
74    pub active: bool,
75    pub lat_target_pct: f64,
76    pub lat_target: f64,
77    pub rps_target_ratio: f64,
78    pub mem_ratio: Option<f64>,
79    pub file_addr_stdev: Option<f64>,
80    pub anon_addr_stdev: Option<f64>,
81    pub file_ratio: f64,
82    pub file_max_ratio: f64,
83    pub log_bps: u64,
84    pub weight: f64,
85}
86
87impl Default for HashdCmd {
88    fn default() -> Self {
89        Self {
90            active: false,
91            lat_target_pct: rd_hashd_intf::Params::default().lat_target_pct,
92            lat_target: rd_hashd_intf::Params::default().lat_target,
93            rps_target_ratio: 0.5,
94            mem_ratio: None,
95            file_addr_stdev: None,
96            anon_addr_stdev: None,
97            file_ratio: rd_hashd_intf::Params::default().file_frac,
98            file_max_ratio: rd_hashd_intf::Args::default().file_max_frac,
99            log_bps: rd_hashd_intf::Params::default().log_bps,
100            weight: 1.0,
101        }
102    }
103}
104
105#[derive(Clone, PartialEq, Serialize, Deserialize)]
106#[serde(default)]
107pub struct Cmd {
108    pub cmd_seq: u64,
109    pub bench_hashd_seq: u64,
110    pub bench_hashd_balloon_size: usize,
111    pub bench_hashd_args: Vec<String>,
112    pub bench_iocost_seq: u64,
113    pub sideloader: SideloaderCmd,
114    pub hashd: [HashdCmd; 2],
115    pub sysloads: BTreeMap<String, String>,
116    pub sideloads: BTreeMap<String, String>,
117    pub swappiness: Option<u32>,
118    pub zswap_enabled: Option<bool>,
119    pub balloon_ratio: f64,
120}
121
122impl Cmd {
123    pub fn bench_hashd_memory_slack(mem_share: usize) -> usize {
124        (mem_share / 8).min(1 << 30)
125    }
126}
127
128impl Default for Cmd {
129    fn default() -> Self {
130        Self {
131            cmd_seq: 0,
132            bench_hashd_seq: 0,
133            bench_hashd_balloon_size: Self::bench_hashd_memory_slack(total_memory()),
134            bench_hashd_args: vec![],
135            bench_iocost_seq: 0,
136            sideloader: SideloaderCmd { cpu_headroom: 0.2 },
137            hashd: Default::default(),
138            sysloads: BTreeMap::new(),
139            sideloads: BTreeMap::new(),
140            swappiness: None,
141            zswap_enabled: None,
142            balloon_ratio: 0.0,
143        }
144    }
145}
146
147impl JsonLoad for Cmd {}
148
149impl JsonSave for Cmd {
150    fn preamble() -> Option<String> {
151        Some(CMD_DOC.clone())
152    }
153}