Fake Rayon (#162)
Dummy implementation of Rayon's traits to avoid `#[cfg()]` and duplicated non-parallel code.
This commit is contained in:
parent
0d4a9e06d6
commit
33890cf0fd
4 changed files with 61 additions and 38 deletions
|
|
@ -9,7 +9,6 @@ use png::STD_COMPRESSION;
|
|||
use png::STD_FILTERS;
|
||||
use png::STD_STRATEGY;
|
||||
use png::STD_WINDOW;
|
||||
#[cfg(feature = "parallel")]
|
||||
use rayon::prelude::*;
|
||||
use std::sync::mpsc::*;
|
||||
use std::sync::Arc;
|
||||
|
|
@ -63,10 +62,7 @@ impl Evaluator {
|
|||
let best_result: Mutex<Option<(PngData, _, _)>> = Mutex::new(None);
|
||||
// ends when sender is dropped
|
||||
for (nth, (image, bias, is_reduction)) in from_channel.iter().enumerate() {
|
||||
#[cfg(feature = "parallel")]
|
||||
let filters_iter = STD_FILTERS.par_iter().with_max_len(1);
|
||||
#[cfg(not(feature = "parallel"))]
|
||||
let filters_iter = STD_FILTERS.iter();
|
||||
|
||||
filters_iter.for_each(|&f| {
|
||||
if let Ok(idat_data) = deflate::deflate(
|
||||
|
|
|
|||
38
src/lib.rs
38
src/lib.rs
|
|
@ -9,6 +9,8 @@ extern crate miniz_oxide;
|
|||
extern crate num_cpus;
|
||||
#[cfg(feature = "parallel")]
|
||||
extern crate rayon;
|
||||
#[cfg(not(feature = "parallel"))]
|
||||
mod rayon;
|
||||
extern crate rgb;
|
||||
extern crate zopfli;
|
||||
|
||||
|
|
@ -21,7 +23,6 @@ use image::{DynamicImage, GenericImageView, ImageFormat, Pixel};
|
|||
use png::PngImage;
|
||||
use png::PngData;
|
||||
use colors::BitDepth;
|
||||
#[cfg(feature = "parallel")]
|
||||
use rayon::prelude::*;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt;
|
||||
|
|
@ -569,10 +570,7 @@ fn optimize_png(png: &mut PngData, original_data: &[u8], opts: &Options) -> PngR
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parallel")]
|
||||
let filter_iter = filter.par_iter().with_max_len(1);
|
||||
#[cfg(not(feature = "parallel"))]
|
||||
let filter_iter = filter.iter();
|
||||
let filters: HashMap<u8, Vec<u8>> = filter_iter
|
||||
.map(|f| {
|
||||
let png = png.clone();
|
||||
|
|
@ -583,10 +581,7 @@ fn optimize_png(png: &mut PngData, original_data: &[u8], opts: &Options) -> PngR
|
|||
let added_interlacing = opts.interlace == Some(1) && original_png.raw.ihdr.interlaced == 0;
|
||||
|
||||
let best_size = AtomicMin::new(if opts.force { None } else { Some(original_len) });
|
||||
#[cfg(feature = "parallel")]
|
||||
let results_iter = results.into_par_iter().with_max_len(1);
|
||||
#[cfg(not(feature = "parallel"))]
|
||||
let results_iter = results.into_iter();
|
||||
let best = results_iter.filter_map(|trial| {
|
||||
if deadline.passed() {
|
||||
return None;
|
||||
|
|
@ -635,20 +630,8 @@ fn optimize_png(png: &mut PngData, original_data: &[u8], opts: &Options) -> PngR
|
|||
None
|
||||
}
|
||||
});
|
||||
#[cfg(feature = "parallel")]
|
||||
let best: Option<TrialWithData> =
|
||||
best.reduce_with(|i, j| if i.1.len() <= j.1.len() { i } else { j });
|
||||
#[cfg(not(feature = "parallel"))]
|
||||
let best: Option<TrialWithData> = best.fold(None, |i, j| {
|
||||
if let Some(i) = i {
|
||||
if i.1.len() <= j.1.len() {
|
||||
Some(i)
|
||||
} else {
|
||||
Some(j)
|
||||
}
|
||||
} else {
|
||||
Some(j)
|
||||
}
|
||||
let best: Option<TrialWithData> = best.reduce_with(|i, j| {
|
||||
if i.1.len() <= j.1.len() { i } else { j }
|
||||
});
|
||||
|
||||
if let Some(better) = best {
|
||||
|
|
@ -704,15 +687,10 @@ fn optimize_png(png: &mut PngData, original_data: &[u8], opts: &Options) -> PngR
|
|||
}
|
||||
}
|
||||
|
||||
let (old_png, new_png) = {
|
||||
let old_png = || image::load_from_memory_with_format(original_data, ImageFormat::PNG);
|
||||
let new_png = || image::load_from_memory_with_format(&output, ImageFormat::PNG);
|
||||
#[cfg(feature = "parallel")]
|
||||
let res = rayon::join(old_png, new_png);
|
||||
#[cfg(not(feature = "parallel"))]
|
||||
let res = (old_png(), new_png());
|
||||
res
|
||||
};
|
||||
let (old_png, new_png) = rayon::join(
|
||||
|| image::load_from_memory_with_format(original_data, ImageFormat::PNG),
|
||||
|| image::load_from_memory_with_format(&output, ImageFormat::PNG)
|
||||
);
|
||||
|
||||
if let Ok(new_png) = new_png {
|
||||
if let Ok(old_png) = old_png {
|
||||
|
|
|
|||
53
src/rayon.rs
Normal file
53
src/rayon.rs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
pub mod prelude {
|
||||
pub use super::*;
|
||||
}
|
||||
|
||||
pub trait ParallelIterator: Iterator + Sized {
|
||||
fn with_max_len(self, _l: usize) -> Self {self}
|
||||
fn reduce_with<OP>(mut self, op: OP) -> Option<Self::Item> where OP: Fn(Self::Item, Self::Item) -> Self::Item + Sync {
|
||||
if let Some(a) = self.next() {
|
||||
Some(self.fold(a, op))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait IntoParallelIterator {
|
||||
type Iter: Iterator<Item=Self::Item>;
|
||||
type Item: Send;
|
||||
fn into_par_iter(self) -> Self::Iter;
|
||||
}
|
||||
|
||||
pub trait IntoParallelRefIterator<'data> {
|
||||
type Iter: Iterator<Item=Self::Item>;
|
||||
type Item: Send + 'data;
|
||||
fn par_iter(&'data self) -> Self::Iter;
|
||||
}
|
||||
|
||||
impl<I: IntoIterator> IntoParallelIterator for I where I::Item: Send {
|
||||
type Iter = I::IntoIter;
|
||||
type Item = I::Item;
|
||||
|
||||
fn into_par_iter(self) -> Self::Iter {
|
||||
self.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'data, I: 'data + ?Sized> IntoParallelRefIterator<'data> for I
|
||||
where &'data I: IntoParallelIterator
|
||||
{
|
||||
type Iter = <&'data I as IntoParallelIterator>::Iter;
|
||||
type Item = <&'data I as IntoParallelIterator>::Item;
|
||||
|
||||
fn par_iter(&'data self) -> Self::Iter {
|
||||
self.into_par_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Iterator> ParallelIterator for I {
|
||||
}
|
||||
|
||||
pub fn join<A, B>(a: impl FnOnce() -> A, b: impl FnOnce() -> B) -> (A, B) {
|
||||
(a(), b())
|
||||
}
|
||||
|
|
@ -7,16 +7,12 @@ use colors::AlphaOptim;
|
|||
use headers::IhdrData;
|
||||
use png::PngImage;
|
||||
use colors::ColorType;
|
||||
#[cfg(feature = "parallel")]
|
||||
use rayon::prelude::*;
|
||||
|
||||
pub fn try_alpha_reductions(png: Arc<PngImage>, alphas: &HashSet<AlphaOptim>, eval: &Evaluator) {
|
||||
assert!(!alphas.is_empty());
|
||||
let alphas = alphas.iter().collect::<Vec<_>>();
|
||||
#[cfg(feature = "parallel")]
|
||||
let alphas_iter = alphas.par_iter().with_max_len(1);
|
||||
#[cfg(not(feature = "parallel"))]
|
||||
let alphas_iter = alphas.iter();
|
||||
alphas_iter
|
||||
.filter_map(|&alpha| filtered_alpha_channel(&png, *alpha))
|
||||
.for_each(|image| eval.try_image(Arc::new(image), 0.99));
|
||||
|
|
|
|||
Loading…
Reference in a new issue