-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Redis PubSub, RedisConn methods no longer require mutable, custom bac…
…kdoor to underlying redis commands in a batch (#57) * No more mutable requirement for redis conns, much more ergonomic * Custom fallbacks to underlying redis interface without having to leave higher level interface * Redis pubsub * Error resistant, more tests, lazy clone.
- Loading branch information
Showing
17 changed files
with
1,164 additions
and
205 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
#![allow(unused_imports)] | ||
use criterion::{black_box, criterion_group, criterion_main, Criterion}; | ||
|
||
// <--- EXAMPLE: | ||
|
||
fn fibonacci(n: u64) -> u64 { | ||
let mut a = 0; | ||
let mut b = 1; | ||
|
||
match n { | ||
0 => b, | ||
_ => { | ||
for _ in 0..n { | ||
let c = a + b; | ||
a = b; | ||
b = c; | ||
} | ||
b | ||
} | ||
} | ||
} | ||
|
||
async fn async_fibonacci(n: u64) -> u64 { | ||
fibonacci(n) | ||
} | ||
|
||
// SYNC EXAMPLE | ||
pub fn bench_sync(c: &mut Criterion) { | ||
c.bench_function("sync: fib 20", |b| b.iter(|| fibonacci(black_box(20)))); | ||
} | ||
|
||
// ASYNC EXAMPLE | ||
pub fn bench_async(c: &mut Criterion) { | ||
c.bench_function("async: fib 20", |b| { | ||
b.to_async(&get_tokio_rt()) | ||
.iter(|| async_fibonacci(black_box(20))) | ||
}); | ||
} | ||
|
||
// CUSTOM CONFIG EXAMPLE | ||
pub fn bench_config(c: &mut Criterion) { | ||
let mut group = c.benchmark_group("small-sample-size"); | ||
group.sample_size(10).significance_level(0.01); | ||
group.bench_function("config: fib 20", |b| b.iter(|| fibonacci(black_box(20)))); | ||
group.finish(); | ||
} | ||
|
||
criterion_group!(benches, bench_sync, bench_async, bench_config); | ||
criterion_main!(benches); | ||
|
||
fn get_tokio_rt() -> tokio::runtime::Runtime { | ||
tokio::runtime::Builder::new_current_thread() | ||
.enable_all() | ||
.build() | ||
.unwrap() | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
/// Efficient way to clone an item for each element in an iterator. | ||
/// The final iteration will consume the original item, so no unnecessary clones are made. | ||
pub trait IterWithCloneLazy { | ||
/// The return type of the iterator. | ||
type IterT; | ||
|
||
/// Efficient way to pass an owned clone of an item to each element in an iterator. | ||
/// Will pass the final item by value without cloning, so no unnecessary clones are made. | ||
fn with_clone_lazy<ItemT: Clone>( | ||
self, | ||
item: ItemT, | ||
) -> impl Iterator<Item = (ItemT, Self::IterT)> | ||
where | ||
Self: Sized; | ||
} | ||
|
||
impl<IterT, I: IntoIterator<Item = IterT>> IterWithCloneLazy for I { | ||
type IterT = IterT; | ||
|
||
fn with_clone_lazy<ItemT: Clone>( | ||
self, | ||
item: ItemT, | ||
) -> impl Iterator<Item = (ItemT, Self::IterT)> | ||
where | ||
Self: Sized, | ||
{ | ||
let mut iter = self.into_iter(); | ||
LazyCloneIter { | ||
item: Some(item), | ||
next_in_iter: iter.next(), | ||
iter, | ||
} | ||
} | ||
} | ||
|
||
struct LazyCloneIter<I: Iterator, ItemT: Clone> { | ||
// Will consume when next_in_iter is None, as on last iteration. | ||
item: Option<ItemT>, | ||
iter: I, | ||
next_in_iter: Option<I::Item>, | ||
} | ||
|
||
impl<I: Iterator, ItemT: Clone> Iterator for LazyCloneIter<I, ItemT> { | ||
type Item = (ItemT, I::Item); | ||
|
||
fn next(&mut self) -> Option<Self::Item> { | ||
self.next_in_iter.take().map(|next| { | ||
self.next_in_iter = self.iter.next(); | ||
if self.next_in_iter.is_none() { | ||
(self.item.take().unwrap(), next) | ||
} else { | ||
(self.item.clone().unwrap(), next) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use std::sync::{atomic::AtomicUsize, Arc}; | ||
|
||
use super::*; | ||
|
||
#[test] | ||
fn test_lazy_clone_with_clone_lazy() { | ||
struct Test { | ||
tot_clones: Arc<AtomicUsize>, | ||
} | ||
impl Clone for Test { | ||
fn clone(&self) -> Self { | ||
self.tot_clones | ||
.fetch_add(1, std::sync::atomic::Ordering::Relaxed); | ||
Test { | ||
tot_clones: self.tot_clones.clone(), | ||
} | ||
} | ||
} | ||
|
||
// Try for 0..10 iterator length, main things to check are 0, 1 and >1. | ||
// For all but final iteration, should clone, then pass by value. | ||
for count in 0..10 { | ||
let tot_clones = Arc::new(AtomicUsize::new(0)); | ||
let test = Test { | ||
tot_clones: tot_clones.clone(), | ||
}; | ||
for (t, index) in (0..count).with_clone_lazy(test) { | ||
assert_eq!( | ||
t.tot_clones.load(std::sync::atomic::Ordering::Relaxed), | ||
if index < count - 1 { index + 1 } else { index } | ||
); | ||
} | ||
assert_eq!( | ||
tot_clones.load(std::sync::atomic::Ordering::Relaxed), | ||
count.max(1) - 1 | ||
); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.