rd_hashd_intf/
params.rs

1// Copyright (c) Facebook, Inc. and its affiliates.
2use anyhow::Result;
3use serde::{Deserialize, Serialize};
4
5use rd_util::*;
6
7#[derive(Clone, Debug, Serialize, Deserialize)]
8pub struct PidParams {
9    pub kp: f64,
10    pub ki: f64,
11    pub kd: f64,
12}
13
14const PARAMS_DOC: &str = "\
15//
16// rd-hashd runtime parameters
17//
18// All parameters can be updated while running and will be applied immediately.
19//
20// rd-hashd keeps calculating SHA1s of different parts of testfiles using
21// concurrent worker threads. The testfile indices and hash sizes are
22// determined using truncated normal distributions which gradually transforms
23// to uniform distributions as their standard deviations increase.
24//
25// All durations are in seconds and memory bytes. A _frac field should be <=
26// 1.0 and specifies a sub-proportion of some other value. A _ratio field is
27// similar but may be greater than 1.0.
28//
29// The concurrency level is modulated using two PID controllers to target the
30// specified latency and RPS so that neither is exceeded. The total number
31// of concurrent threads is limited by `concurrency_max`.
32//
33// The total size of testfiles is set up during startup and can't be changed
34// online. However, the portion which is actively used by rd-hashd can be
35// scaled down with `file_total_frac`.
36//
37// Anonymous memory total and access sizes are configured as proportions to
38// file access sizes.
39//
40// The total footprint for file accesses is scaled between
41// `file_addr_rps_base_frac` and 1.0 linearly if the current RPS is lower than
42// `rps_max`. If `rps_max` is 0, access footprint scaling is disabled. Anon
43// footprint is scaled the same way between 'anon_addr_rps_base_frac' and 1.0.
44//
45// Worker threads will sleep according to the sleep duration distribution and
46// their CPU consumption can be scaled up and down using `cpu_ratio`.
47//
48//  control_period: PID control period, best left alone
49//  concurrency_max: Maximum number of worker threads
50//  lat_target_pct: Latency target percentile
51//  lat_target: Latency target
52//  rps_target: Request-per-second target
53//  rps_max: Reference maximum RPS, used to scale the amount of used memory
54//  chunk_pages: Memory access chunk size in pages
55//  mem_frac: Memory footprint scaling factor - [0.0, 1.0]
56//  file_frac: Page cache proportion of memory footprint - [0.0, 1.0]
57//  file_size_mean: File access size average
58//  file_size_stdev_ratio: Standard deviation of file access sizes
59//  file_addr_stdev_ratio: Standard deviation of file access addresses
60//  file_addr_rps_base_frac: Memory scaling starting point for file accesses
61//  file_write_frac: The proportion of writes in file accesses
62//  anon_size_ratio: Anon access size average - 1.0 means equal as file accesses
63//  anon_size_stdev_ratio: Standard deviation of anon access sizes
64//  anon_addr_stdev_ratio: Standard deviation of anon access addresses
65//  anon_addr_rps_base_frac: Memory scaling starting point for anon accesses
66//  anon_write_frac: The proportion of writes in anon accesses
67//  sleep_mean: Worker sleep duration average
68//  sleep_stdev_ratio: Standard deviation of sleep duration distribution
69//  cpu_ratio: CPU usage scaling - 1.0 hashes the same number of bytes as accessed
70//  log_bps: Log write bps at rps_max
71//  fake_cpu_load: Sleep equivalent time durations instead of calculating SHA1s
72//  acc_dist_slots: Access distribution report slots - 0 disables
73//  lat_pid: PID controller parameters for latency convergence
74//  rps_pid: PID controller parameters for RPS convergence
75//
76";
77
78/// Dispatch and hash parameters, can be adjusted dynamially.
79#[derive(Clone, Debug, Serialize, Deserialize)]
80#[serde(default)]
81pub struct Params {
82    pub control_period: f64,
83    pub concurrency_max: u32,
84    pub lat_target_pct: f64,
85    pub lat_target: f64,
86    pub rps_target: u32,
87    pub rps_max: u32,
88    pub mem_frac: f64,
89    pub chunk_pages: usize,
90    pub file_frac: f64,
91    pub file_size_mean: usize,
92    pub file_size_stdev_ratio: f64,
93    pub file_addr_stdev_ratio: f64,
94    pub file_addr_rps_base_frac: f64,
95    pub file_write_frac: f64,
96    pub anon_size_ratio: f64,
97    pub anon_size_stdev_ratio: f64,
98    pub anon_addr_stdev_ratio: f64,
99    pub anon_addr_rps_base_frac: f64,
100    pub anon_write_frac: f64,
101    pub sleep_mean: f64,
102    pub sleep_stdev_ratio: f64,
103    pub cpu_ratio: f64,
104    pub log_bps: u64,
105    pub fake_cpu_load: bool,
106    pub acc_dist_slots: usize,
107    pub lat_pid: PidParams,
108    pub rps_pid: PidParams,
109}
110
111impl Params {
112    pub const FILE_FRAC_MIN: f64 = 0.001;
113
114    pub fn log_padding(&self) -> u64 {
115        if self.rps_max > 0 {
116            (self.log_bps as f64 / self.rps_max as f64).round() as u64
117        } else {
118            0
119        }
120    }
121}
122
123impl Default for Params {
124    fn default() -> Self {
125        Self {
126            control_period: 1.0,
127            concurrency_max: 65536,
128            lat_target_pct: 0.95,
129            lat_target: 75.0 * MSEC,
130            rps_target: 65536,
131            rps_max: 0,
132            chunk_pages: 25,
133            mem_frac: 0.80,
134            file_frac: 0.25,
135            file_size_mean: 1258291,
136            file_size_stdev_ratio: 0.45,
137            file_addr_stdev_ratio: 0.215,
138            file_addr_rps_base_frac: 0.5,
139            file_write_frac: 0.0,
140            anon_size_ratio: 2.3,
141            anon_size_stdev_ratio: 0.45,
142            anon_addr_stdev_ratio: 0.235,
143            anon_addr_rps_base_frac: 0.5,
144            anon_write_frac: 0.3,
145            sleep_mean: 20.0 * MSEC,
146            sleep_stdev_ratio: 0.33,
147            cpu_ratio: 0.93,
148            log_bps: 1100794,
149            fake_cpu_load: false,
150            acc_dist_slots: 0,
151            lat_pid: PidParams {
152                kp: 0.1,
153                ki: 0.01,
154                kd: 0.01,
155            },
156            rps_pid: PidParams {
157                kp: 0.25,
158                ki: 0.01,
159                kd: 0.01,
160            },
161        }
162    }
163}
164
165impl JsonLoad for Params {
166    fn loaded(&mut self, _prev: Option<&mut Self>) -> Result<()> {
167        self.file_frac = self.file_frac.max(Self::FILE_FRAC_MIN);
168        Ok(())
169    }
170}
171
172impl JsonSave for Params {
173    fn preamble() -> Option<String> {
174        Some(PARAMS_DOC.to_string())
175    }
176}