overkill with tokio
cargo devel CI / cargo CI (push) Successful in 1m34s Details

This commit is contained in:
Christoph J. Scherr 2024-04-17 14:13:48 +02:00
parent 37ce70d23b
commit 628c5163a5
4 changed files with 32 additions and 43 deletions

View File

@ -36,6 +36,7 @@ serde = { version = "1.0.197", optional = true, features = ["serde_derive"] }
serde_json = { version = "1.0.114", optional = true } serde_json = { version = "1.0.114", optional = true }
# serde_with = "3.7.0" # serde_with = "3.7.0"
thiserror = "1.0.58" thiserror = "1.0.58"
tokio = { version = "1.37.0", features = ["macros", "rt", "rt-multi-thread", "time"] }
[[bin]] [[bin]]
name = "wordlec" name = "wordlec"

View File

@ -1,23 +1,18 @@
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, RwLock};
use std::thread::JoinHandle;
use libpt::log::info; use libpt::log::info;
use crate::error::{BenchError, Error, WResult}; use crate::game::{self, GameBuilder};
use crate::game::{self, Game, GameBuilder};
use crate::solve::Solver; use crate::solve::Solver;
use crate::wlist::WordList; use crate::wlist::WordList;
use super::{Benchmark, Report}; use super::{Benchmark, Report};
use rayon::prelude::*;
#[derive(Debug)] #[derive(Debug)]
pub struct BuiltinBenchmark<'wl, WL: WordList, SL: Solver<'wl, WL>> { pub struct BuiltinBenchmark<'wl, WL: WordList, SL: Solver<'wl, WL>> {
solver: SL, solver: SL,
builder: GameBuilder<'wl, WL>, builder: GameBuilder<'wl, WL>,
report: Arc<RwLock<Report>>, report: Arc<RwLock<Report>>,
benchth: Option<JoinHandle<()>>,
} }
impl<'wl, WL, SL> Benchmark<'wl, WL, SL> for BuiltinBenchmark<'wl, WL, SL> impl<'wl, WL, SL> Benchmark<'wl, WL, SL> for BuiltinBenchmark<'wl, WL, SL>
@ -43,7 +38,6 @@ where
solver, solver,
report: Arc::new(RwLock::new(Report::new(builder.build()?))), report: Arc::new(RwLock::new(Report::new(builder.build()?))),
builder, builder,
benchth: None,
}) })
} }
fn solver(&self) -> SL { fn solver(&self) -> SL {
@ -66,26 +60,4 @@ where
fn report(&'wl self) -> super::Report { fn report(&'wl self) -> super::Report {
self.report.read().expect("lock is poisoned").clone() 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<bool> {
match &self.benchth {
Some(th) => Some(th.is_finished()),
None => None,
}
}
} }

View File

@ -1,7 +1,6 @@
use std::fmt::Debug; use std::fmt::Debug;
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, RwLock};
use libpt::log::debug;
use rayon::prelude::*; use rayon::prelude::*;
use crate::error::WResult; use crate::error::WResult;
@ -42,13 +41,12 @@ where
fn play(&'wl self) -> WResult<GuessResponse> { fn play(&'wl self) -> WResult<GuessResponse> {
self.solver_ref().play(&mut self.make_game()?) self.solver_ref().play(&mut self.make_game()?)
} }
fn start(&'wl self, n: usize) -> WResult<()>;
fn is_finished(&self) -> Option<bool>;
// TODO: add some interface to get reports while the benchmark runs // TODO: add some interface to get reports while the benchmark runs
// TODO: make the benchmark optionally multithreaded // TODO: make the benchmark optionally multithreaded
// NOTE: This is blocking, use start to let it run in another thread // NOTE: This is blocking, use start to let it run in another thread
#[deprecated] // HACK: Shame on me, but I cannot find out how to share the data over threads, so that we can
fn bench(&'wl self, n: usize) -> WResult<Report> { // make this a start function and just poll records while rayon does the benching.
async fn bench(&'wl self, n: usize) -> WResult<Report> {
let report = self.report_shared(); let report = self.report_shared();
let this = std::sync::Arc::new(self); let this = std::sync::Arc::new(self);

View File

@ -45,7 +45,8 @@ struct Cli {
threads: usize, threads: usize,
} }
fn main() -> anyhow::Result<()> { #[tokio::main]
async fn main() -> anyhow::Result<()> {
let cli = Cli::parse(); let cli = Cli::parse();
if cli.verbose { if cli.verbose {
Logger::build_mini(Some(Level::DEBUG))?; Logger::build_mini(Some(Level::DEBUG))?;
@ -60,16 +61,33 @@ fn main() -> anyhow::Result<()> {
.max_steps(cli.max_steps) .max_steps(cli.max_steps)
.precompute(cli.precompute); .precompute(cli.precompute);
let solver: AnyBuiltinSolver<'_, BuiltinWList> = cli.solver.to_solver(&wl); 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:#?}"); trace!("{bench:#?}");
let n = cli.n;
bench.start(n)?;
while bench.is_finished().is_some_and(|b| b) { loop {
println!("{}", bench.report()); 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 // FIXME: Rustc thinks wl is borrowed at this point, but it is not!!!!! Or at least it should
// not be // not be
Ok(()) Ok(())