Add option to disable parallel file processing (#695)
Fixes #685. Fixes #572. Also fixes #690 by using "logical CPUs".
This commit is contained in:
parent
d168fffb12
commit
a44ba5f88b
2 changed files with 52 additions and 28 deletions
21
src/cli.rs
21
src/cli.rs
|
|
@ -350,16 +350,31 @@ timeout before each transformation or compression trial, and will stop trying to
|
|||
the file if the timeout is exceeded. Note that this does not cut short any operations that \
|
||||
are already in progress, so it is currently of limited effectiveness for large files with \
|
||||
high compression levels.")
|
||||
.value_name("secs")
|
||||
.long("timeout")
|
||||
.value_name("secs")
|
||||
.value_parser(value_parser!(u64)),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("threads")
|
||||
.help("Set number of threads to use [default: num CPU cores]")
|
||||
.long("threads")
|
||||
.help("Number of threads to use [default: num logical CPUs]")
|
||||
.long_help("\
|
||||
Set the maximum number of threads to use. Oxipng uses multithreading to evaluate multiple \
|
||||
optimizations on the same file in parallel as well as process multiple files in parallel. \
|
||||
You can set this to a lower value if you need to limit memory or CPU usage.
|
||||
|
||||
[default: num logical CPUs]")
|
||||
.short('t')
|
||||
.long("threads")
|
||||
.value_name("num")
|
||||
.value_parser(value_parser!(usize)),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("parallel-files")
|
||||
.help("Process multiple files sequentially")
|
||||
.long_help("\
|
||||
Process multiple files sequentially rather than in parallel. Use this if you need \
|
||||
determinism in the processing order. Note this is not necessary if using '--threads 1'.")
|
||||
.long("sequential")
|
||||
.action(ArgAction::SetFalse),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
59
src/main.rs
59
src/main.rs
|
|
@ -72,32 +72,20 @@ fn main() -> ExitCode {
|
|||
true,
|
||||
);
|
||||
|
||||
let summary = files
|
||||
.into_par_iter()
|
||||
.map(|(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(_) => OptimizationResult::Ok,
|
||||
Err(e @ PngError::C2PAMetadataPreventsChanges) => {
|
||||
warn!("{input}: {e}");
|
||||
OptimizationResult::Skipped
|
||||
}
|
||||
Err(e) => {
|
||||
error!("{input}: {e}");
|
||||
OptimizationResult::Failed
|
||||
}
|
||||
}
|
||||
})
|
||||
.min()
|
||||
.unwrap_or(OptimizationResult::Skipped);
|
||||
let parallel_files = matches.get_flag("parallel-files");
|
||||
let summary = if parallel_files {
|
||||
files
|
||||
.into_par_iter()
|
||||
.map(|(input, output)| process_file(&input, &output, &opts))
|
||||
.min()
|
||||
} else {
|
||||
files
|
||||
.into_iter()
|
||||
.map(|(input, output)| process_file(&input, &output, &opts))
|
||||
.min()
|
||||
};
|
||||
|
||||
match summary {
|
||||
match summary.unwrap_or(OptimizationResult::Skipped) {
|
||||
OptimizationResult::Ok => ExitCode::SUCCESS,
|
||||
OptimizationResult::Failed => ExitCode::FAILURE,
|
||||
OptimizationResult::Skipped => ExitCode::from(3),
|
||||
|
|
@ -421,3 +409,24 @@ fn parse_numeric_range_opts(
|
|||
|
||||
Err(ERROR_MESSAGE.to_owned())
|
||||
}
|
||||
|
||||
fn process_file(input: &InFile, output: &OutFile, opts: &Options) -> OptimizationResult {
|
||||
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(_) => OptimizationResult::Ok,
|
||||
Err(e @ PngError::C2PAMetadataPreventsChanges) => {
|
||||
warn!("{input}: {e}");
|
||||
OptimizationResult::Skipped
|
||||
}
|
||||
Err(e) => {
|
||||
error!("{input}: {e}");
|
||||
OptimizationResult::Failed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue