generated from PlexSheep/rs-base
async in sync is hard
cargo devel CI / cargo CI (push) Failing after 1m12s
Details
cargo devel CI / cargo CI (push) Failing after 1m12s
Details
This commit is contained in:
parent
0cd46eb2de
commit
91911fca1d
|
@ -1,4 +1,6 @@
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::atomic::AtomicBool;
|
||||||
|
use std::sync::{Arc, Mutex, RwLock};
|
||||||
|
use std::thread::JoinHandle;
|
||||||
|
|
||||||
use libpt::log::info;
|
use libpt::log::info;
|
||||||
|
|
||||||
|
@ -9,12 +11,13 @@ use crate::wlist::WordList;
|
||||||
|
|
||||||
use super::{Benchmark, Report};
|
use super::{Benchmark, Report};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[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>>,
|
||||||
finished: bool
|
finished: AtomicBool,
|
||||||
|
bench_th: Arc<Mutex<Option<JoinHandle<WResult<Report>>>>> // HACK: this is unholy
|
||||||
}
|
}
|
||||||
|
|
||||||
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>
|
||||||
|
@ -32,42 +35,51 @@ where
|
||||||
threads: usize,
|
threads: usize,
|
||||||
) -> crate::error::WResult<Self> {
|
) -> crate::error::WResult<Self> {
|
||||||
info!("using {threads} threads for benchmarking");
|
info!("using {threads} threads for benchmarking");
|
||||||
rayon::ThreadPoolBuilder::new()
|
|
||||||
.num_threads(threads)
|
|
||||||
.build_global()
|
|
||||||
.unwrap();
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
solver,
|
solver,
|
||||||
report: Arc::new(RwLock::new(Report::new(builder.build()?))),
|
report: Arc::new(RwLock::new(Report::new(builder.build()?))),
|
||||||
builder,
|
builder,
|
||||||
finished: false
|
finished: AtomicBool::new(false),
|
||||||
|
bench_th: Arc::new(Mutex::new(None))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
fn solver(&self) -> SL {
|
fn solver(&self) -> SL {
|
||||||
self.solver.clone()
|
self.solver.clone()
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
fn builder(&'wl self) -> game::GameBuilder<'wl, WL> {
|
fn builder(&'wl self) -> game::GameBuilder<'wl, WL> {
|
||||||
self.builder.clone()
|
self.builder.clone()
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
fn solver_ref(&'wl self) -> &'wl SL {
|
fn solver_ref(&'wl self) -> &'wl SL {
|
||||||
&self.solver
|
&self.solver
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
fn builder_ref(&'wl self) -> &'wl game::GameBuilder<'wl, WL> {
|
fn builder_ref(&'wl self) -> &'wl game::GameBuilder<'wl, WL> {
|
||||||
&self.builder
|
&self.builder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn report_shared(&'wl self) -> Arc<RwLock<Report>> {
|
fn report_shared(&'wl self) -> Arc<RwLock<Report>> {
|
||||||
self.report.clone()
|
self.report.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
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 is_finished(&self) -> bool {
|
fn is_finished(&self) -> bool {
|
||||||
self.finished
|
self.finished.load(std::sync::atomic::Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
fn start(&self) -> WResult<()> {
|
fn start(&'wl self, n: usize) -> WResult<()> {
|
||||||
todo!();
|
let report = self.report_shared();
|
||||||
|
let solver = self.solver();
|
||||||
|
let builder = self.builder();
|
||||||
|
let th = std::thread::spawn(move||{
|
||||||
|
Self::bench(n, report, solver, builder)
|
||||||
|
});
|
||||||
|
*self.bench_th.lock().expect("lock is poisoned") = Some(th);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ pub mod builtin;
|
||||||
/// Default amount of games to play for a [Benchmark]
|
/// Default amount of games to play for a [Benchmark]
|
||||||
pub const DEFAULT_N: usize = 50;
|
pub const DEFAULT_N: usize = 50;
|
||||||
|
|
||||||
pub trait Benchmark<'wl, WL, SL>: Sized + Debug + Sync + Clone
|
pub trait Benchmark<'wl, WL, SL>: Sized + Debug + Sync
|
||||||
where
|
where
|
||||||
WL: WordList,
|
WL: WordList,
|
||||||
WL: 'wl,
|
WL: 'wl,
|
||||||
|
@ -44,28 +44,25 @@ where
|
||||||
// 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
|
||||||
fn bench(&'wl self, n: usize) -> WResult<Report> {
|
fn bench(n: usize, report: Arc<RwLock<Report>>, solver: SL, builder: GameBuilder<'wl, WL>) -> WResult<Report> {
|
||||||
let report = self.report_shared();
|
|
||||||
let this = std::sync::Arc::new(self);
|
|
||||||
|
|
||||||
(0..n)
|
(0..n)
|
||||||
.into_par_iter()
|
.into_par_iter()
|
||||||
.for_each_with(report.clone(), |outside_data, _i| {
|
.for_each_with(report.clone(), |outside_data, _i| {
|
||||||
let report = outside_data;
|
let report = outside_data;
|
||||||
let r = this
|
let r = solver
|
||||||
.play()
|
.play(&mut builder.build().expect("could not create game"))
|
||||||
.expect("error playing the game during benchmark");
|
.expect("error playing the game during benchmark");
|
||||||
report.write().expect("lock is poisoned").add(r);
|
report.write().expect("lock is poisoned").add(r);
|
||||||
});
|
});
|
||||||
|
|
||||||
report.write().expect("lock is poisoned").finalize();
|
report.write().expect("lock is poisoned").finalize();
|
||||||
drop(report);
|
|
||||||
|
|
||||||
Ok(self.report())
|
Ok(report.read().expect("lock is poisoned").clone())
|
||||||
}
|
}
|
||||||
// PERF: Somehow returning &Report would be better as we don't need to clone then
|
// PERF: Somehow returning &Report would be better as we don't need to clone then
|
||||||
fn report(&'wl self) -> Report;
|
fn report(&'wl self) -> Report;
|
||||||
fn report_shared(&'wl self) -> Arc<RwLock<Report>>;
|
fn report_shared(&'wl self) -> Arc<RwLock<Report>>;
|
||||||
fn start(&self) -> WResult<()>;
|
fn start(&'wl self, n: usize) -> WResult<()>;
|
||||||
fn is_finished(&self) -> bool;
|
fn is_finished(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue