Skip to content

Commit

Permalink
Add more hints
Browse files Browse the repository at this point in the history
Add hints for the starting TPS and the Latency Controller.
  • Loading branch information
byronwasti committed Jul 23, 2024
1 parent 721b96c commit f79f0c7
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 13 deletions.
1 change: 0 additions & 1 deletion Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ prep:
cargo fmt --all -- --check
cargo clippy --all-targets -- -D warnings
cargo test --release
cargo semver-checks

version EXECUTE='' VERSION='minor':
cargo release version -p balter -p balter-macros -p balter-core -p balter-runtime {{VERSION}} {{EXECUTE}}
Expand Down
4 changes: 4 additions & 0 deletions balter-core/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,16 @@ impl LatencyConfig {
#[cfg_attr(feature = "rt", derive(Serialize, Deserialize))]
pub struct HintConfig {
pub concurrency: usize,
pub starting_tps: Option<NonZeroU32>,
pub latency_controller: Option<f64>,
}

impl Default for HintConfig {
fn default() -> Self {
Self {
concurrency: crate::BASE_CONCURRENCY,
starting_tps: None,
latency_controller: None,
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ expression: "ScenarioConfig {\n name: \"test_scenario\".to_string(),\n dur
"quantile": 0.99
},
"hints": {
"concurrency": 10
"concurrency": 10,
"starting_tps": null,
"latency_controller": null
}
}
23 changes: 17 additions & 6 deletions balter/src/controllers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub(crate) trait Controller: Send {

pub(crate) struct CompositeController {
controllers: Vec<Box<dyn Controller>>,
starting_tps: Option<NonZeroU32>,
}

impl CompositeController {
Expand All @@ -36,20 +37,30 @@ impl CompositeController {
&config.name,
latency,
quantile,
config.hints.latency_controller,
)));
}

Self { controllers }
let starting_tps = config.hints.starting_tps;

Self {
controllers,
starting_tps,
}
}
}

impl Controller for CompositeController {
fn initial_tps(&self) -> NonZeroU32 {
self.controllers
.iter()
.map(|c| c.initial_tps())
.min()
.expect("No controllers present.")
if let Some(tps) = self.starting_tps {
tps
} else {
self.controllers
.iter()
.map(|c| c.initial_tps())
.min()
.expect("No controllers present.")
}
}

fn limit(&mut self, sample: &Measurement, stable: bool) -> NonZeroU32 {
Expand Down
8 changes: 5 additions & 3 deletions balter/src/controllers/latency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,25 @@ use std::time::Duration;
#[allow(unused)]
use tracing::{debug, error, trace};

const KP: f64 = 0.9;
const DEFAULT_KP: f64 = 0.9;

#[allow(unused)]
pub(crate) struct LatencyController {
base_label: String,
latency: Duration,
quantile: f64,
goal_tps: NonZeroU32,
kp: f64,
}

impl LatencyController {
pub fn new(name: &str, latency: Duration, quantile: f64) -> Self {
pub fn new(name: &str, latency: Duration, quantile: f64, kp: Option<f64>) -> Self {
let s = Self {
base_label: format!("balter_{name}"),
latency,
quantile,
goal_tps: BASE_TPS,
kp: kp.unwrap_or(DEFAULT_KP),
};
s.goal_tps_metric();
s
Expand All @@ -49,7 +51,7 @@ impl Controller for LatencyController {
let normalized_err = 1. - measured_latency.as_secs_f64() / self.latency.as_secs_f64();
trace!("LATENCY: Error {normalized_err:?}");

let new_goal = self.goal_tps.get() as f64 * (1. + KP * normalized_err);
let new_goal = self.goal_tps.get() as f64 * (1. + self.kp * normalized_err);
trace!("LATENCY: New Goal {new_goal:?}");

if let Some(new_goal) = NonZeroU32::new(new_goal as u32) {
Expand Down
7 changes: 7 additions & 0 deletions balter/src/hints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,11 @@ pub enum Hint {
/// Provide the starting concurrency value. Useful for Scenarios with low TPS (which Balter can
/// take a long time to stablize on).
Concurrency(usize),

/// Starting TPS for Balter to use.
Tps(u32),

/// Kp value for the Latency Controller proportional control loop
/// Defaults to 0.9
LatencyController(f64),
}
7 changes: 7 additions & 0 deletions balter/src/scenario.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,13 @@ where
Hint::Concurrency(concurrency) => {
self.config.hints.concurrency = concurrency;
}
Hint::Tps(tps) => {
self.config.hints.starting_tps =
Some(NonZeroU32::new(tps).expect("TPS hint must be non-zero u32"));
}
Hint::LatencyController(kp) => {
self.config.hints.latency_controller = Some(kp);
}
}
self
}
Expand Down
28 changes: 26 additions & 2 deletions docs/content/guide/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,11 @@ test_scaling_functionality()
.await;
```

### Hints
## Hints

For certain Scenarios it can be useful to provide hints for how Balter should run them. This is primarily useful for speeding up the control loops that Balter uses internally, which are designed to work for a wide variety of use-cases and can sometimes be slow. Currently Balter provides one kind of hint, the `Hint::Concurrency` which Balter will use as the starting concurrency for a given Scenario:
For certain Scenarios it can be useful to provide hints for how Balter should run them. This is primarily useful for speeding up the control loops that Balter uses internally, which are designed to work for a wide variety of use-cases and can sometimes be slow. Currently Balter provides only a few hints.

- `Hint::Concurrency` which Balter will use as the starting concurrency for a given Scenario:

```rust
use balter::{prelude::*, Hint};
Expand All @@ -141,6 +143,28 @@ my_scenario()
.await;
```

- `Hint::Tps` which Balter will use as the starting TPS for a given Scenario:

```rust
use balter::{prelude::*, Hint};

my_scenario()
.tps(10_000)
.hint(Hint::Tps(10_000))
.await;
```

- `Hint::LatencyController` which sets the `Kp` value used by the proportional control loop in the Latency Controller. Use to speed up convergence, though beware of instability. Defaults to `0.9`.

```rust
use balter::{prelude::*, Hint};

my_scenario()
.tps(10_000)
.hint(Hint::Latency(1.2))
.await;
```

## Statistics

Scenario's will return statistical information about the run. For example,
Expand Down

0 comments on commit f79f0c7

Please sign in to comment.