72

I would like to limit the amount of CPU time dedicated to certain processes (e.g. Firefox, Safari, ...).

I can't understand why such programs, even when not used (nothing loading, no animations, running in the background, ...), are so resource hungry. Why must a browser eat 50% or more of my CPU? Can I limit it to 10%?

4
  • I can barely get Safari to use 10% of my CPU with about 20 windows open, so I'd suggest trying to find out why the app is using those resources and fix it, rather than just limiting the resources it can use.
    – benwiggy
    Sep 13 '20 at 15:53
  • 1
    @benwiggy - Luky you. The fact is that an application can behave as it likes, e.g. it can pretend to use all the resources available in the system, either on purpose or because of a bug. It is the operating system that must constrain every application so that all the processes have their share of the CPU time. And the user must be able to let the OS know which processes have priority under his point of view. Also consider that many computers work with batteries... so energy consumption is another factor to be kept in cosideration.
    – Pietro
    Sep 15 '20 at 10:46
  • 1
    One thing to note is that 100% CPU usage on a 2020 MacBook Air is actually 12.5% usage (8 core CPU means it has 800% capacity).
    – Ezekiel
    Mar 27 at 22:13
  • Do any of the solutions not relying on SIGSTOP or renice work on M1/Apple Silicon? cputhrottle (willnolan.com/cputhrottle/cputhrottle.html) does NOT run, at least not with SIP (System Integrity Protection) enabled. It does compile, but the mach call fails: libc++abi: terminating with uncaught exception of type Process::ManipulatorException: Error on task_for_pid of pid XXXX, res = 5 Sep 20 at 5:28

15 Answers 15

14

Its not exactly what you wanted, but, in regards of google drive and chrome this what did the trick for me:

Google Drive ("Backup and Sync")

  • de-prioritize:

    for f in $(pgrep 'Backup and Sync'; pgrep 'FinderSyncAPIExtension'); do renice +20 -p $f; done
    
  • set back to normal:

    for f in $(pgrep 'Backup and Sync'; pgrep 'FinderSyncAPIExtension'); do renice 0 -p $f; done
    

Chrome

  • de-prioritize all current processes:

    for f in $(pgrep 'Chrome'); do renice +20 -p $f; done
    
  • set back to normal all current processes:

    for f in $(pgrep 'Chrome'); do renice 0 -p $f; done
    
1
  • 1
    +1 - This is the most correct answer offered because 'nice' is part of the OS and directly ties into the algorithm used by the kernel's scheduler to decide which process gets the next slice of CPU time. It will always work on any Unix or Linux system and is not dependent on any 3rd party add-one. The bonus is that those processes can use more CPU if they aren't competing for CPU time with other processes. Sep 12 '20 at 21:26
46

cputhrottle is the tool you need. You can install it with Homebrew.

You can monitor a series of processes by name by running the Bash script below. I'm not quite sure how to turn this into a login item since cputhrottle requires superuser permissions. Run it as a script, in an Automator workflow, whatever:

# Get the Process/App names from Activity Monitor and put them here
apps=("AppOne" "AppTwo" "AppThree")
# Set the respective limits here
limits={30 40 50)

while true; do
  for app in ${apps}; do
    for limit in ${limits}; do
      for pid in $(pgrep ${app}); do
        sudo /path/to/cputhrottle ${pid} ${limit}
      done
    done
  done
done

[Edited]

I've added a different version for this script (a bash script), which might be useful for people looking for limiting the CPU for multiple applications.

This new script also allows you to specify a list containing the application name and the CPU limit for it.

The main difference is that you can add cpu limit per application, and it will run only once per application. I've also added the option for killing all cputhrottle processes.

The script assumes that both cputhrottle and pidof are installed before running it.

#!/bin/bash

if [[ $EUID > 0 ]]; then
  echo "Please run this script as root/sudo"
  exit 1
fi

# Pass --kill as argument to kill all running cputhrottles
if [ $1 = "--kill" ]; then  
  echo "Looking for running cputhrottles..."
  pids=`pidof cputhrottle`
  for pid in ${pids}; do
    echo "> Killing PID ${pid}"
    sudo kill ${pid}
  done
  echo "Done!"
  exit 0
fi

declare -a applications

# Syntax='application;max-cpu'
applications[0]='Chrome;40'
applications[1]='Firefox;50'
applications[2]='pycharm;40'
applications[3]='webstorm;40'
applications[4]='Safari;35'

for i in "${applications[@]}"; do
  app=(${i//;/ })
  app_name=${app[0]}
  cpu_limit=${app[1]}

  printf "\nLooking for ${app_name}...\n"
  pids=`pidof ${app}`
  for pid in ${pids}; do
    echo "> PID=${pid}, CPU=${cpu_limit}"
    sudo cputhrottle ${pid} ${cpu_limit} &
  done
done

printf "\nDone!\n"
echo "Run this script passing '--kill' as argument to remove all cputhrottles."

Source:

6
17

You can indeed! There's CPUThrottle, which allows to specify a PID to restrict.

Note, they're trying to use that much for a reason, it's a useful tool but whether it'll make it better or worse for you on a day to day will be something you discover.

4
  • 1
    Interesting. But with this utility I have to launch a program, find its PID(s) and manually use cputhrottle. Every time I launch it. Is there something that allows me to tell the system: “From today always run this program with a maximum of 25% CPU” ?
    – Pietro
    Sep 14 '11 at 10:45
  • As far as I'm aware no, I've only ever come across CPUThrottle. Sep 14 '11 at 11:03
  • 1
    404 File not found Jul 31 '19 at 0:47
  • As posted above,CPUThrottle is here : medium.com/@sbr464/… Sep 15 '20 at 21:44
13

Although not a direct answer to the OP's question, if you're having an issue with a particular process taking up too much of your CPU time, and making your computer unusable, and you don't mind how long that process takes to finish the task it's working on, you can use the renice to alter the priority of that process, making it behave nicely (hence the name).

First, you need to find the PID of the process that's using up the CPU resources. You can either do that in Activity Monitor, or in Terminal.app with the ps command - e.g. to find the PID of the Safari browser, type:

MacBook:~😈  ps -ef | grep Safari
  501 17452   263   0 11:36pm ??         4:15.60 /Applications/Safari.app/Contents/MacOS/Safari

The second line above is the output, and the PID is 17452 in this particular case.

Then, the next task is to change the priority of the process (let's say it's Safari we want to make behave nicely). To do this, in Terminal.app type:

MacBook:~😈  renice -n 10 -p 17452

The -n option changes the nice level by adding 10 to the current value (0 by default). The range of values are -20 to 20, with lowest value meaning highest priority. As an ordinary user, you can use values 0 to 20. To assign a negative value, you need to have root privileges (e.g. use sudo command). Read more about nice and renice by typing man nice and man renice in Terminal.app.

nice and renice don't limit the percentage of the CPU available to a given application per se, they do however allow to change the scheduling priority, or in other words how much of the CPU time a process will get. This is all relative to the CPU load on your system, so if the system is under utilised, you most likely won't see any difference.

2
  • Is there a way to see the current priority of a process? Oct 23 '17 at 21:07
  • use top or htop to view the current nice value of a process. (brew install htop), (sudo apt install htop). You'll see one of the columns containing the value.
    – Tmanok
    Dec 19 '18 at 5:22
9

The link that Nicholas Smith posted doesn't work anymore. So I found one other app that does the trick for the people who are searching it again. the app calls Apppolice.

http://www.macupdate.com/app/mac/49836/apppolice

9
  • 3
    Similar to AppPolice, there is AppTamer (stclairsw.com/AppTamer). One word of caution: as of me writing this comment, AppTamer has yet to be OSX Sierra compatible. Oct 21 '16 at 15:48
  • 1
    Oh my, what a find. Just installed AppTamer. Pleased to report works fantastically well. I use it to keep the new StarCraft remastered in line when I alt-tab out. Oh and I forgot to mention, I'm running macOS Sierra 10.12.6. Thanks for the suggestion!
    – cavalcade
    Aug 23 '17 at 15:23
  • Apppolice has been discontinued. Sep 27 '17 at 16:48
  • But still works quite fine. Jul 2 '19 at 14:13
  • 2
    Brilliant find. Apppolice is much less complicated (and hence more troublefree) than fancypants AppTamer. Here's my mini review: Found the release over here on GitHub, installed, limited Lightroom Classic to 1600%, saw its CPU usage drop from 2200% to 1473% immediately. Have my computer back to work on while Lightroom imports 150,000 photos. I could see this as very useful for DaVinci Resolve renders as well. So simple to use. Brilliant. PS. Normally I don't use Lightroom, prefer FastRawViewer and DxO PhotoLab but need a catalogue of everything to merge some hard drives. Aug 22 '20 at 14:04
5

This is based off a previous answer, but adding the trap for ctrl+c to make sure the process being throttled gets left in a continue state, and adding set -e so this script will exit cleanly if the process itself exits:

trap ctrl_c_fn INT

function ctrl_c_fn() {
    echo "caught CTRL-C, exiting"
    kill -SIGCONT $pid
    exit
}

echo "enter process id"
read pid
echo "press Ctrl-C to exit"

set -e

while true; do
    kill -SIGSTOP $pid
    sleep 0.009
    kill -SIGCONT $pid
    sleep 0.001
done
5

There is a simple one-liner for doing all that:

ps axu | grep Chromium | grep -v grep | awk '{print $2}' | sudo xargs -n 1 -I'{}' sh -c 'cputhrottle {} 10 &'

Write your app name instead of Chromium and desired percentage instead of 10 and you're good to go!

3
  • This worked well, though it can be reduced to: pgrep Dropbox | sudo xargs -n 1 -I'{}' sh -c 'cputhrottle {} 10 &'. I'm not sure if macOS comes with pgrep installed, however.
    – bigsweater
    Oct 1 '18 at 21:19
  • 3
    cputhrottle no longer works on 10.14 Mojave
    – John Pang
    Dec 15 '19 at 23:47
  • cputhrottle works on 10.15 so if it wasn't working on Mojave, it might be now.
    – TJ Luoma
    Jan 4 '20 at 3:01
3

this sh worked for me

echo "enter process id"
read pid
echo "press Ctrl-C to exit"

while true; do
    kill -SIGSTOP $pid
    sleep 0.009
    kill -SIGCONT $pid
    sleep 0.001
done
3

The script Dimitri wrote does work well (on macOS), but it keeps running with errors after the application is closed. I changed it to make it finish (with an error message about PID not found):

echo "enter process id"
read pid
echo "press Ctrl-C to exit"

while kill -SIGSTOP $pid; do
    sleep 0.009
    kill -SIGCONT $pid
    sleep 0.001
done
1
  • This should probably be an edit made to Dimitri's original answer, in order to improve that answer, and not a separate answer with (basically) the same info.
    – fsb
    Aug 4 '18 at 14:34
3

I just found CPUSetter, which, for me, is better than any of the previous options.

This app comes with additional control over hyperthreading, number of used cores, preference of physical CPU and separate power-related settings.

2

This is my final script, keep clean the command cputhrottle only execute new one if doesn't exist

#!/bin/bash

###
# setup cputhrottle if doesn't exists
###
set_service_cpu_limit(){
    service_pid=$(pgrep $1)
    limit=$2
    if [[ ! -z $service_pid  ]]; then
        service_cpu=$(ps aux | grep "sudo cputhrottle $service_pid $limit" | grep -v grep | wc -l)
        if [[ ! $service_cpu -gt 0 ]]; then
            sudo cputhrottle $service_pid $limit &
        fi
    fi
}

###
# main loop
###
while true; do
    set_service_cpu_limit bzfilelist 2
    set_service_cpu_limit bztransmit 2
    sleep 0.5
done
2

I use AppPolice. It is a bit unstable and clunky but since there are no other options and the problems are minor I think it is a decent solution. Works on Catalina.

3
  • Except there are other options, such as AppTamer which is actually still under development.
    – TJ Luoma
    Jan 4 '20 at 2:43
  • This worked for me
    – atreeon
    May 25 '20 at 13:23
  • In macOS Mojave I don't find AppPolice to be unstable at all.
    – MiB
    Apr 7 at 12:52
1

cputhrottle (refer to fny and Nicholas Smith's answers) works on macOS 10.15 as long as you sign the executable.

You can do so simply and quickly by following the steps listed here: https://web.archive.org/web/20191223180139/https://sourceware.org/gdb/wiki/PermissionsDarwin

You can download cputhrottle here: http://www.willnolan.com/cputhrottle/cputhrottle.html

4
  • Where would find find “cputhrottle”. And its better to include the essentials of the the link because they oftentimes go stale making the answer useless
    – Allan
    Jul 2 '20 at 2:10
  • @Allan, thanks. I added some extra links. I would have left my answer as a comment originally on the other answers but I don't have enough reputation.
    – Lambo
    Jul 2 '20 at 14:50
  • That's a different CPUThrottle, as far as I'm aware. The original one referred to above, which was on Homebrew, can be found here : medium.com/@sbr464/… I haven't tried the Will Nola one : All I see is it's a significantly smaller executable. Any idea why ? Sep 15 '20 at 21:49
  • @JPGConnolly the medium.com article links to Will Nolan's site. As for the binary sizes, when I built it for my machine with march=native, the executable was <20KiB, so there can be a lot of bloat based on compilation settings.
    – Lambo
    Feb 17 at 14:18
0

This script is what I use: this code runs the app at full speed when the screen is locked else it runs at about 50% of the speed. On my M1 Pro MacBook Pro this works great for an app that normally takes 800% CPU. The computer remains responsive while the app is running in background.

#!/bin/bash

PID=$1

if [ "$PID" == "" ]; then
    echo "no process id given! Use something like:"
    echo "   ps -ef|grep whatever"
    exit
fi

# exit if any command fails
set -e
# continue running when we exit this script
trap 'kill -CONT '$PID'; exit' EXIT HUP TERM INT

status=none
prevstatus=none

while true; do
    if [ "$status" != "$prevstatus" ]; then
        date
        echo $status
        prevstatus=$status
    fi
    if python -c 'import sys,Quartz; d=Quartz.CGSessionCopyCurrentDictionary(); print d'|grep "CGSSessionScreenIsLocked = 1">/dev/null; then
        if [ "$status" != "running" ]; then
            kill -CONT $PID;
            status=running
        fi
        sleep 1;
    else
        if [ "$status" != "stopped" ]; then
            kill -STOP $PID;
            status=stopped
        else
            for _ in {1..10}; do
                sleep 0.05;
                kill -CONT $PID;
                sleep 0.05;
                kill -STOP $PID;
            done
        fi
    fi;
done

-1

Some others have mentioned App Tamer and the fact that AppPolice is free. That's great, and if AppPolice meets your needs, you can be happy!

But if you use your computer professionally, the time you've lost on processes sucking down resources is probably vastly higher than the tiny cost of AppTamer.

All the options that AppTamer offers that AppPolice does not are there for a reason.

AppPolice requires you to configure each process individually. The only thing it can do globally is stop throttling. (Which could be done by closing it anyway.)

AppTamer on the other hand can distinguish before foreground and background apps, so that you can throttle an app in the background but give it full power in the foreground. Browsers, for example.

AppTamer

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .