fn bench_memio_saturation_bisect()

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)(&params, 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(&params);

            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(&params);

                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)(&params, 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(&params);

            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]
    }