3

I have this code to optimize image size of all my images inside /dir directory:

find /dir/ -iregex ".*\.\(jpg\|jpeg\)" -exec jpegoptim --strip-all {} \;

When I run this code, it consumes a lot of my server CPU. So I am wondering: is it possible to me add a delay between each exec? For example, I want 100 miliseconds of delay between each time exec is called to every image, this way the CPU does not get very busy.

What would you suggest? My server is running Centos 8.

1
  • 2
    Why do you want your CPUs not to get busy? Are you afraid they may get tired :-) or is there maybe some more important task your server is meant to do that shouldn't be delayed by that image trimming activity and all your CPU cores are already close to saturation? Nov 3, 2021 at 11:19

4 Answers 4

10

You could also add more commands using more -execs

find /dir/ -iregex ".*\.\(jpg\|jpeg\)" -exec jpegoptim --strip-all {} \; -exec sleep 0.1 \;

But as a general rule, if you want to have it working full but being nice to other processes, it's very simple to use nice:

nice find /dir/ -iregex ".*\.\(jpg\|jpeg\)" -exec jpegoptim --strip-all {} \;
1
8

This is the reason that commands like nice and ionice were created.

  • nice can be used to reduce the process CPU priority
  • ionice can be used to reduce the process IO priority

A combination of these can ensure that your process takes only a small slice of the available processor and IO capability. This example pushes the process IO into the lowest end of the "best effort" class:

ionice -c2 -n7 find...

Change -c2 to -c3 to ensure your process will only run when the IO subsystem is otherwise idle.

This example drops the processor allowance to a low priority:

nice -n12 find...

Change -n12 to -n19 for the least possible priority.

Combine them for maximum effect:

ionice -c2 -n7 nice -n12 find...
3

You could use a shell loop with -exec option of find that runs a for loop running jpegoptim for every image file found, with an added delay

find /dir/ -iregex ".*\.\(jpg\|jpeg\)" -exec sh -c '
  for file; do jpegoptim --strip-all "$file"; sleep 0.1; done' -- {} +
3

By using -exec cmd ... {} ';', you're running one instance of cmd for each file. jpegoptim can process more than one file per invocation, so you would avoid your CPUs a lot of work by changing it to -exec cmd ... {} +:

LC_ALL=C nice find . '(' -name '*.[jJ][pP][gG]' -o -name '*.[jJ][pP][eE][gG]' ')' \
  -type f -exec jpegoptim --strip-all {} +

(here with the find command converted to standard syntax and improved so it matches on all filenames that end in .jpg or .jpeg case insensitively, and restricted to regular files).

nice tells the scheduler to prioritize other tasks over the ones that are running find or jpegoptim. It's a lot more efficient than putting those tasks to sleep arbitrarily even when your processors have plenty of time to spare (also consider that it takes some CPU time to execute, load, initialise, etc a sleep utility).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.