Skip to content

Commit

Permalink
add floor to latency score
Browse files Browse the repository at this point in the history
  • Loading branch information
Theodus committed May 25, 2024
1 parent 4c4e08f commit 373e702
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 3 deletions.
4 changes: 4 additions & 0 deletions candidate-selection/src/num.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ impl Normalized {
Some(Self(value))
}

pub fn clamp(value: f64, min: f64, max: f64) -> Option<Self> {
Self::new(value.clamp(min, max))
}

pub fn as_inner(&self) -> NotNan<f64> {
self.0
}
Expand Down
6 changes: 3 additions & 3 deletions indexer-selection/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,11 @@ fn score_zero_allocation(zero_allocation: bool) -> Normalized {
/// https://www.desmos.com/calculator/v2vrfktlpl
pub fn score_latency(latency_ms: u16) -> Normalized {
let s = |x: u16| 1.0 + E.powf(((x as f64) - 400.0) / 300.0);
Normalized::new(s(0) / s(latency_ms)).unwrap()
// Since high latency becomes bad success rate via timeouts, latency scores should have a floor.
Normalized::clamp(s(0) / s(latency_ms), 0.001, 1.0).unwrap()
}

/// https://www.desmos.com/calculator/df2keku3ad
fn score_success_rate(success_rate: Normalized) -> Normalized {
let min_score = 1e-8;
Normalized::new(success_rate.as_f64().powi(7).max(min_score)).unwrap()
Normalized::clamp(success_rate.as_f64().powi(7), 1e-8, 1.0).unwrap()
}
56 changes: 56 additions & 0 deletions indexer-selection/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,62 @@ fn sensitivity_seconds_behind() {
);
}

#[test]
fn sensitivity_seconds_behind_vs_latency() {
let candidates = [
Candidate {
indexer: hex!("0000000000000000000000000000000000000000").into(),
deployment: hex!("0000000000000000000000000000000000000000000000000000000000000000")
.into(),
url: "https://example.com".parse().unwrap(),
perf: ExpectedPerformance {
success_rate: Normalized::new(0.99).unwrap(),
latency_ms: 0,
},
fee: Normalized::ZERO,
seconds_behind: 35_000_000,
slashable_grt: 1_600_000,
versions_behind: 0,
zero_allocation: false,
},
Candidate {
indexer: hex!("0000000000000000000000000000000000000001").into(),
deployment: hex!("0000000000000000000000000000000000000000000000000000000000000000")
.into(),
url: "https://example.com".parse().unwrap(),
perf: ExpectedPerformance {
success_rate: Normalized::new(0.99).unwrap(),
latency_ms: 10_000,
},
fee: Normalized::ZERO,
seconds_behind: 120,
slashable_grt: 100_000,
versions_behind: 0,
zero_allocation: true,
},
];

println!(
"score {} {:?}",
candidates[0].indexer,
candidates[0].score(),
);
println!(
"score {} {:?}",
candidates[1].indexer,
candidates[1].score(),
);
assert!(candidates[0].score() <= candidates[1].score());

let selections: ArrayVec<&Candidate, 3> = crate::select(&candidates);
assert_eq!(1, selections.len(), "select exatly one candidate");
assert_eq!(
Some(candidates[1].indexer),
selections.first().map(|s| s.indexer),
"select candidate closer to chain head",
);
}

#[test]
fn multi_selection_preference() {
let candidates = [
Expand Down

0 comments on commit 373e702

Please sign in to comment.