From 628c5163a5a9a90a1093d86114602d0fd9e846af Mon Sep 17 00:00:00 2001 From: PlexSheep Date: Wed, 17 Apr 2024 14:13:48 +0200 Subject: [PATCH] overkill with tokio --- Cargo.toml | 1 + src/bench/builtin.rs | 32 ++------------------------------ src/bench/mod.rs | 10 ++++------ src/bin/bench/cli.rs | 32 +++++++++++++++++++++++++------- 4 files changed, 32 insertions(+), 43 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4e6d0de..f5a7ccf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,7 @@ serde = { version = "1.0.197", optional = true, features = ["serde_derive"] } serde_json = { version = "1.0.114", optional = true } # serde_with = "3.7.0" thiserror = "1.0.58" +tokio = { version = "1.37.0", features = ["macros", "rt", "rt-multi-thread", "time"] } [[bin]] name = "wordlec" diff --git a/src/bench/builtin.rs b/src/bench/builtin.rs index adf49d5..5afd7a5 100644 --- a/src/bench/builtin.rs +++ b/src/bench/builtin.rs @@ -1,23 +1,18 @@ -use std::sync::{Arc, Mutex, RwLock}; -use std::thread::JoinHandle; +use std::sync::{Arc, RwLock}; use libpt::log::info; -use crate::error::{BenchError, Error, WResult}; -use crate::game::{self, Game, GameBuilder}; +use crate::game::{self, GameBuilder}; use crate::solve::Solver; use crate::wlist::WordList; use super::{Benchmark, Report}; -use rayon::prelude::*; - #[derive(Debug)] pub struct BuiltinBenchmark<'wl, WL: WordList, SL: Solver<'wl, WL>> { solver: SL, builder: GameBuilder<'wl, WL>, report: Arc>, - benchth: Option>, } impl<'wl, WL, SL> Benchmark<'wl, WL, SL> for BuiltinBenchmark<'wl, WL, SL> @@ -43,7 +38,6 @@ where solver, report: Arc::new(RwLock::new(Report::new(builder.build()?))), builder, - benchth: None, }) } fn solver(&self) -> SL { @@ -66,26 +60,4 @@ where fn report(&'wl self) -> super::Report { self.report.read().expect("lock is poisoned").clone() } - - fn start(&'wl self, n: usize) -> WResult<()> { - let report = self.report_shared(); // FIXME: needs to keep self borrowed for some reason? - let solver = self.solver(); - let builder = self.builder(); - let benchth = std::thread::spawn({ - move || { - // TODO: do the stuff - report.write().expect("lock is poisoned").finalize(); - } - }); - - // self.benchth = Some(benchth); - Ok(()) - } - - fn is_finished(&self) -> Option { - match &self.benchth { - Some(th) => Some(th.is_finished()), - None => None, - } - } } diff --git a/src/bench/mod.rs b/src/bench/mod.rs index b674731..489a83c 100644 --- a/src/bench/mod.rs +++ b/src/bench/mod.rs @@ -1,7 +1,6 @@ use std::fmt::Debug; -use std::sync::{Arc, Mutex, RwLock}; +use std::sync::{Arc, RwLock}; -use libpt::log::debug; use rayon::prelude::*; use crate::error::WResult; @@ -42,13 +41,12 @@ where fn play(&'wl self) -> WResult { self.solver_ref().play(&mut self.make_game()?) } - fn start(&'wl self, n: usize) -> WResult<()>; - fn is_finished(&self) -> Option; // TODO: add some interface to get reports while the benchmark runs // TODO: make the benchmark optionally multithreaded // NOTE: This is blocking, use start to let it run in another thread - #[deprecated] - fn bench(&'wl self, n: usize) -> WResult { + // HACK: Shame on me, but I cannot find out how to share the data over threads, so that we can + // make this a start function and just poll records while rayon does the benching. + async fn bench(&'wl self, n: usize) -> WResult { let report = self.report_shared(); let this = std::sync::Arc::new(self); diff --git a/src/bin/bench/cli.rs b/src/bin/bench/cli.rs index bb05494..7dd32c1 100644 --- a/src/bin/bench/cli.rs +++ b/src/bin/bench/cli.rs @@ -45,7 +45,8 @@ struct Cli { threads: usize, } -fn main() -> anyhow::Result<()> { +#[tokio::main] +async fn main() -> anyhow::Result<()> { let cli = Cli::parse(); if cli.verbose { Logger::build_mini(Some(Level::DEBUG))?; @@ -60,16 +61,33 @@ fn main() -> anyhow::Result<()> { .max_steps(cli.max_steps) .precompute(cli.precompute); let solver: AnyBuiltinSolver<'_, BuiltinWList> = cli.solver.to_solver(&wl); - let mut bench = BuiltinBenchmark::build(&wl, solver, builder, cli.threads)?; + let bench = BuiltinBenchmark::build(&wl, solver, builder, cli.threads)?; trace!("{bench:#?}"); - let n = cli.n; - bench.start(n)?; - while bench.is_finished().is_some_and(|b| b) { - println!("{}", bench.report()); + loop { + match tokio::time::timeout( + tokio::time::Duration::from_millis(10), + bench.bench(cli.n), + ) + .await + { + Ok(result) => { + match result { + Ok(final_report) => { + println!("{}", final_report); + } + Err(err) => { + error!("error while benchmarking: {err:#?}"); + } + } + break; + } + Err(_timeout) => { + println!("{}", bench.report()); + } + } } - // FIXME: Rustc thinks wl is borrowed at this point, but it is not!!!!! Or at least it should // not be Ok(())