Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Process files in parallel #531

Merged
merged 2 commits into from
Jul 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -453,13 +453,15 @@ pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<(
// Run the optimizer on the decoded PNG.
let mut optimized_output = optimize_png(&mut png, &in_data, opts, deadline)?;

let in_length = in_data.len();

if is_fully_optimized(in_data.len(), optimized_output.len(), opts) {
info!("File already optimized");
match (output, input) {
// if p is None, it also means same as the input path
(OutFile::Path(ref p), InFile::Path(ref input_path))
if p.as_ref().map_or(true, |p| p == input_path) =>
{
info!("{}: Could not optimize further, no change written", input);
return Ok(());
}
_ => {
Expand All @@ -468,8 +470,22 @@ pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<(
}
}

let savings = if in_length >= optimized_output.len() {
format!(
"{} bytes ({:.2}% smaller)",
optimized_output.len(),
(in_length - optimized_output.len()) as f64 / in_length as f64 * 100_f64
)
} else {
format!(
"{} bytes ({:.2}% larger)",
optimized_output.len(),
(optimized_output.len() - in_length) as f64 / in_length as f64 * 100_f64
)
};

if opts.pretend {
info!("Running in pretend mode, no output");
info!("{}: Running in pretend mode, no output", savings);
return Ok(());
}

Expand Down Expand Up @@ -516,7 +532,7 @@ pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<(
if let Some(metadata_input) = &opt_metadata_preserved {
copy_times(metadata_input, output_path)?;
}
info!("Output: {}", output_path.display());
info!("{}: {}", savings, output_path.display());
}
}
Ok(())
Expand Down Expand Up @@ -606,14 +622,14 @@ fn optimize_png(
);
}
if file_original_size >= output.len() {
info!(
debug!(
" file size = {} bytes ({} bytes = {:.2}% decrease)",
output.len(),
file_original_size - output.len(),
(file_original_size - output.len()) as f64 / file_original_size as f64 * 100_f64
);
} else {
info!(
debug!(
" file size = {} bytes ({} bytes = {:.2}% increase)",
output.len(),
output.len() - file_original_size,
Expand Down
22 changes: 12 additions & 10 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#![warn(clippy::range_plus_one)]
#![allow(clippy::cognitive_complexity)]

#[cfg(not(feature = "parallel"))]
mod rayon;

use clap::{value_parser, Arg, ArgAction, ArgMatches, Command};
use indexmap::IndexSet;
use log::{error, warn};
Expand All @@ -21,6 +24,7 @@ use oxipng::Options;
use oxipng::RowFilter;
use oxipng::StripChunks;
use oxipng::{InFile, OutFile};
use rayon::prelude::*;
use std::fs::DirBuilder;
#[cfg(feature = "zopfli")]
use std::num::NonZeroU8;
Expand Down Expand Up @@ -313,26 +317,24 @@ Heuristic filter selection strategies:
true,
);

let mut success = false;
for (input, output) in files {
match oxipng::optimize(&input, &output, &opts) {
let success = files.into_par_iter().filter(|(input, output)| {
match oxipng::optimize(input, output, &opts) {
// For optimizing single files, this will return the correct exit code always.
// For recursive optimization, the correct choice is a bit subjective.
// We're choosing to return a 0 exit code if ANY file in the set
// runs correctly.
// The reason for this is that recursion may pick up files that are not
// PNG files, and return an error for them.
// We don't really want to return an error code for those files.
Ok(_) => {
success = true;
}
Ok(_) => true,
Err(e) => {
error!("{}", e);
error!("{}: {}", input, e);
false
}
};
}
}
});

if !success {
if success.count() == 0 {
exit(1);
}
}
Expand Down
1 change: 1 addition & 0 deletions src/rayon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ pub fn join<A, B>(a: impl FnOnce() -> A, b: impl FnOnce() -> B) -> (A, B) {
(a(), b())
}

#[allow(dead_code)]
pub fn spawn<A>(a: impl FnOnce() -> A) -> A {
a()
}
1 change: 1 addition & 0 deletions tests/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ fn verbose_mode() {
"Found better combination:",
" zc = 11 f = None ",
" IDAT size = ",
" file size = ",
];
assert_eq!(logs.len(), expected_prefixes.len());
for (i, log) in logs.into_iter().enumerate() {
Expand Down
Loading