wordle-analyzer/src/bench/mod.rs
PlexSheep e6934bfb08
Some checks failed
cargo devel CI / cargo CI (push) Failing after 1m16s
move report to struct so that users of the lib can pull
2024-04-05 20:00:33 +02:00

67 lines
1.9 KiB
Rust

use std::fmt::Debug;
use std::sync::{Arc, Mutex};
use libpt::log::debug;
use rayon::prelude::*;
use crate::error::WResult;
use crate::game::response::GuessResponse;
use crate::game::{Game, GameBuilder};
use crate::solve::Solver;
use crate::wlist::WordList;
pub mod report;
use report::*;
#[cfg(feature = "builtin")]
pub mod builtin;
/// Default amount of games to play for a [Benchmark]
pub const DEFAULT_N: usize = 50;
pub trait Benchmark<'wl, WL, SL>: Clone + Sized + Debug + Sync
where
WL: WordList,
WL: 'wl,
SL: Solver<'wl, WL>,
SL: 'wl,
{
fn build(
wordlist: &'wl WL,
solver: SL,
builder: GameBuilder<'wl, WL>,
threads: usize
) -> crate::error::WResult<Self>;
fn builder(&'wl self) -> &'wl GameBuilder<'wl, WL>;
fn make_game(&'wl self) -> WResult<Game<'wl, WL>> {
Ok(self.builder().build()?)
}
fn solver(&'wl self) -> &'wl SL;
fn play(&'wl self) -> WResult<GuessResponse> {
self.solver().play(&mut self.make_game()?)
}
// TODO: add some interface to get reports while the benchmark runs
// TODO: make the benchmark optionally multithreaded
fn bench(&'wl self, n: usize) -> WResult<Report> {
let report = self.report_mutex();
let this = std::sync::Arc::new(self);
(0..n)
.into_par_iter()
.for_each_with(report.clone(), |outside_data, _i| {
let report = outside_data;
let r = this
.play()
.expect("error playing the game during benchmark");
report.lock().expect("lock is poisoned").add(r);
});
report.lock().expect("lock is poisoned").finalize();
drop(report);
Ok(self.report())
}
// PERF: Somehow returning &Report would be better as we don't need to clone then
fn report(&'wl self) -> Report;
fn report_mutex(&'wl self) -> Arc<Mutex<Report>>;
}