Skip to content

Instantly share code, notes, and snippets.

@ljedrz

ljedrz/main.rs Secret

Created July 31, 2018 16:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ljedrz/c2fcc19f6260976ae7a46ae47aa71fb5 to your computer and use it in GitHub Desktop.
Save ljedrz/c2fcc19f6260976ae7a46ae47aa71fb5 to your computer and use it in GitHub Desktop.
Benchmarks for collecting into Option and Result
#![feature(test)]
extern crate test;
use test::Bencher;
use std::iter::FromIterator;
fn result_from_iter_old<A, E, V: FromIterator<A>, I: IntoIterator<Item=Result<A, E>>>(iter: I) -> Result<V, E> {
struct Adapter<Iter, E> {
iter: Iter,
err: Option<E>,
}
impl<T, E, Iter: Iterator<Item=Result<T, E>>> Iterator for Adapter<Iter, E> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
match self.iter.next() {
Some(Ok(value)) => Some(value),
Some(Err(err)) => {
self.err = Some(err);
None
}
None => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (_min, max) = self.iter.size_hint();
(0, max)
}
}
let mut adapter = Adapter { iter: iter.into_iter(), err: None };
let v: V = FromIterator::from_iter(adapter.by_ref());
match adapter.err {
Some(err) => Err(err),
None => Ok(v),
}
}
fn result_from_iter_new<A, E, V: FromIterator<A>, I: IntoIterator<Item=Result<A, E>>>(iter: I) -> Result<V, E> {
struct Adapter<Iter, E> {
iter: Iter,
err: Option<E>,
}
impl<T, E, Iter: Iterator<Item=Result<T, E>>> Iterator for Adapter<Iter, E> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
match self.iter.next() {
Some(Ok(value)) => Some(value),
Some(Err(err)) => {
self.err = Some(err);
None
}
None => None,
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
if self.err.is_some() {
(0, Some(0))
} else {
self.iter.size_hint()
}
}
}
let mut adapter = Adapter { iter: iter.into_iter(), err: None };
let v: V = FromIterator::from_iter(adapter.by_ref());
match adapter.err {
Some(err) => Err(err),
None => Ok(v),
}
}
fn option_from_iter_old<A, V: FromIterator<A>, I: IntoIterator<Item=Option<A>>>(iter: I) -> Option<V> {
struct Adapter<Iter> {
iter: Iter,
found_none: bool,
}
impl<T, Iter: Iterator<Item=Option<T>>> Iterator for Adapter<Iter> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
match self.iter.next() {
Some(Some(value)) => Some(value),
Some(None) => {
self.found_none = true;
None
}
None => None,
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
if self.found_none {
(0, Some(0))
} else {
let (_, upper) = self.iter.size_hint();
(0, upper)
}
}
}
let mut adapter = Adapter { iter: iter.into_iter(), found_none: false };
let v: V = FromIterator::from_iter(adapter.by_ref());
if adapter.found_none {
None
} else {
Some(v)
}
}
fn option_from_iter_new<A, V: FromIterator<A>, I: IntoIterator<Item=Option<A>>>(iter: I) -> Option<V> {
struct Adapter<Iter> {
iter: Iter,
found_none: bool,
}
impl<T, Iter: Iterator<Item=Option<T>>> Iterator for Adapter<Iter> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
match self.iter.next() {
Some(Some(value)) => Some(value),
Some(None) => {
self.found_none = true;
None
}
None => None,
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
if self.found_none {
(0, Some(0))
} else {
self.iter.size_hint()
}
}
}
let mut adapter = Adapter { iter: iter.into_iter(), found_none: false };
let v: V = FromIterator::from_iter(adapter.by_ref());
if adapter.found_none {
None
} else {
Some(v)
}
}
fn push_loop_to_result<T: Iterator<Item = Result<usize, ()>>>(iter: T) -> Result<Vec<usize>, ()> {
let mut vec = Vec::with_capacity(100);
for e in iter {
vec.push(e?);
}
Ok(vec)
}
fn push_loop_to_option<T: Iterator<Item = Option<usize>>>(iter: T) -> Option<Vec<usize>> {
let mut vec = Vec::with_capacity(100);
for e in iter {
vec.push(e?);
}
Some(vec)
}
fn collect_to_result_old<T: Iterator<Item = Result<usize, ()>>>(iter: T) -> Result<Vec<usize>, ()> {
result_from_iter_old(iter)
}
fn collect_to_result_new<T: Iterator<Item = Result<usize, ()>>>(iter: T) -> Result<Vec<usize>, ()> {
result_from_iter_new(iter)
}
fn collect_to_option_old<T: Iterator<Item = Option<usize>>>(iter: T) -> Option<Vec<usize>> {
option_from_iter_old(iter)
}
fn collect_to_option_new<T: Iterator<Item = Option<usize>>>(iter: T) -> Option<Vec<usize>> {
option_from_iter_new(iter)
}
#[bench]
fn bench_push_loop_to_result(b: &mut Bencher) {
b.iter(|| push_loop_to_result((0..100).map(|e| Ok(e))))
}
#[bench]
fn bench_push_loop_to_option(b: &mut Bencher) {
b.iter(|| push_loop_to_option((0..100).map(|e| Some(e))))
}
#[bench]
fn bench_collect_to_result_old(b: &mut Bencher) {
b.iter(|| collect_to_result_old((0..100).map(|e| Ok(e))))
}
#[bench]
fn bench_collect_to_result_new(b: &mut Bencher) {
b.iter(|| collect_to_result_new((0..100).map(|e| Ok(e))))
}
#[bench]
fn bench_collect_to_option_old(b: &mut Bencher) {
b.iter(|| collect_to_option_old((0..100).map(|e| Some(e))))
}
#[bench]
fn bench_collect_to_option_new(b: &mut Bencher) {
b.iter(|| collect_to_option_new((0..100).map(|e| Some(e))))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment