solver.rs (3431B)
1 use criterion::criterion_group; 2 use criterion::criterion_main; 3 use criterion::Criterion; 4 5 use futures::stream::Collect; 6 use futures::stream::FuturesOrdered; 7 use futures::StreamExt; 8 use l10nregistry_tests::solver::get_scenarios; 9 use l10nregistry::solver::{AsyncTester, ParallelProblemSolver, SerialProblemSolver, SyncTester}; 10 use std::future::Future; 11 use std::pin::Pin; 12 use std::task::{Context, Poll}; 13 14 pub struct MockTester { 15 values: Vec<Vec<bool>>, 16 } 17 18 impl SyncTester for MockTester { 19 fn test_sync(&self, res_idx: usize, source_idx: usize) -> bool { 20 self.values[res_idx][source_idx] 21 } 22 } 23 24 pub struct SingleTestResult(bool); 25 26 impl Future for SingleTestResult { 27 type Output = bool; 28 29 fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> { 30 self.0.into() 31 } 32 } 33 34 pub type ResourceSetStream = Collect<FuturesOrdered<SingleTestResult>, Vec<bool>>; 35 pub struct TestResult(ResourceSetStream); 36 37 impl std::marker::Unpin for TestResult {} 38 39 impl Future for TestResult { 40 type Output = Vec<bool>; 41 42 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 43 let pinned = Pin::new(&mut self.0); 44 pinned.poll(cx) 45 } 46 } 47 48 impl AsyncTester for MockTester { 49 type Result = TestResult; 50 51 fn test_async(&self, query: Vec<(usize, usize)>) -> Self::Result { 52 let futures = query 53 .into_iter() 54 .map(|(res_idx, source_idx)| SingleTestResult(self.test_sync(res_idx, source_idx))) 55 .collect::<Vec<_>>(); 56 TestResult(futures.into_iter().collect::<FuturesOrdered<_>>().collect()) 57 } 58 } 59 60 struct TestStream<'t> { 61 solver: ParallelProblemSolver<MockTester>, 62 tester: &'t MockTester, 63 } 64 65 impl<'t> TestStream<'t> { 66 pub fn new(solver: ParallelProblemSolver<MockTester>, tester: &'t MockTester) -> Self { 67 Self { solver, tester } 68 } 69 } 70 71 impl<'t> futures::stream::Stream for TestStream<'t> { 72 type Item = Vec<usize>; 73 74 fn poll_next( 75 mut self: std::pin::Pin<&mut Self>, 76 cx: &mut std::task::Context<'_>, 77 ) -> std::task::Poll<Option<Self::Item>> { 78 let tester = self.tester; 79 let solver = &mut self.solver; 80 let pinned = std::pin::Pin::new(solver); 81 pinned 82 .try_poll_next(cx, tester, false) 83 .map(|v| v.ok().flatten()) 84 } 85 } 86 87 fn solver_bench(c: &mut Criterion) { 88 let scenarios = get_scenarios(); 89 90 let mut group = c.benchmark_group("solver"); 91 92 for scenario in scenarios { 93 let tester = MockTester { 94 values: scenario.values.clone(), 95 }; 96 97 group.bench_function(&format!("serial/{}", &scenario.name), |b| { 98 b.iter(|| { 99 let mut gen = SerialProblemSolver::new(scenario.width, scenario.depth); 100 while let Ok(Some(_)) = gen.try_next(&tester, false) {} 101 }) 102 }); 103 104 { 105 let rt = tokio::runtime::Runtime::new().unwrap(); 106 107 group.bench_function(&format!("parallel/{}", &scenario.name), |b| { 108 b.iter(|| { 109 let gen = ParallelProblemSolver::new(scenario.width, scenario.depth); 110 let mut t = TestStream::new(gen, &tester); 111 rt.block_on(async { while let Some(_) = t.next().await {} }); 112 }) 113 }); 114 } 115 } 116 group.finish(); 117 } 118 119 criterion_group!(benches, solver_bench); 120 criterion_main!(benches);