in rd-hashd/src/bench.rs [929:1056]
fn bench_memio_saturation_bisect(&mut self, cfg: &MemIoSatCfg, th: &mut TestHasher) -> f64 {
let mut params: Params = self.params.clone();
params.rps_target = self.params.rps_max;
//
// Up-rounds - Coarsely scan up using bisect cfg to determine the first
// resistance point. This phase is necessary because too high a memory
// or io target can cause severe system-wide thrashing.
//
self.set_phase(Phase::BenchMemUp);
let mut round = 0;
let mut next_pos = None;
let mut pos = 0.0;
loop {
round += 1;
next_pos = (cfg.next_up_pos)(¶ms, next_pos);
if next_pos.is_none() {
break;
}
pos = next_pos.unwrap();
self.set_mem_pos(cfg, &mut params, pos);
th.disp_hist.lock().unwrap().disp.set_params(¶ms);
info!(
"[ {} saturation: up-round {}, rps {}, {} {} ]",
cfg.name,
round,
self.params.rps_max,
cfg.pos_prefix,
&(cfg.fmt_pos)(self, pos)
);
if cfg.test || self.memio_up_round(cfg, &cfg.up_converge, &th) {
break;
}
}
if next_pos.is_none() {
info!(
"[ {} saturation: max {} doesn't saturate, using as-is ]",
cfg.name,
(cfg.fmt_pos)(self, pos),
);
return pos;
}
//
// Bisect-rounds - Bisect looking for the saturation point.
//
self.set_phase(Phase::BenchMemBisect);
let mut left = VecDeque::<f64>::from(vec![0.0]);
let mut right = VecDeque::<f64>::from(vec![pos]);
loop {
loop {
pos = (left[0] + right[0]) / 2.0;
info!(
"[ {} saturation: bisection, rps {}, {} {} ]",
cfg.name,
self.params.rps_max,
cfg.pos_prefix,
&(cfg.fmt_pos)(self, pos)
);
self.show_bisection(cfg, &left, pos, &right);
self.set_mem_pos(cfg, &mut params, pos);
th.disp_hist.lock().unwrap().disp.set_params(¶ms);
if self.memio_bisect_round(cfg, &cfg.bisect_converge, &th) {
right.push_front(pos);
} else {
left.push_front(pos);
}
if cfg.test || (cfg.bisect_done)(¶ms, left[0], right[0]) {
break;
}
}
if cfg.test {
break;
}
// Memory response can be delayed and we can end up on the wrong
// side. If there's space to bisect on the other side, make sure
// that it is behaving as expected and if not shift in there.
let was_right = pos == right[0];
if was_right {
if left.len() == 1 {
break;
}
pos = left[0];
} else {
if right.len() == 1 {
break;
}
pos = right[0];
};
self.set_mem_pos(cfg, &mut params, pos);
info!(
"[ {} saturation: re-verifying the opposite bound, {} {} ]",
cfg.name,
cfg.pos_prefix,
&(cfg.fmt_pos)(self, pos)
);
self.show_bisection(cfg, &left, pos, &right);
th.disp_hist.lock().unwrap().disp.set_params(¶ms);
if self.memio_bisect_round(cfg, &cfg.bisect_converge, &th) {
if was_right {
right.pop_back();
right.push_front(left.pop_front().unwrap());
} else {
break;
}
} else {
if !was_right {
left.pop_back();
left.push_front(right.pop_front().unwrap());
} else {
break;
}
}
}
right[0]
}