August 4, 2009

Using CPULimit to prevent Firefox+ Flash CPU Overrun.

Ever had this situation?  Go to Youtube to watch the latest fashion in wedding dances, and suddenly your CPU goes to 98% and everything on ..... the ..... box ........ slows ............ to ........ a ........ crawl.   Well there is a way to prevent that overrun and get back control of your system. 

A  project caled CPULimit at sourceforge has for me presented an answer. In a nutshell what it does for your system is tell a running process that it can't consume more than X percent of the CPU max.  In practice on my laptop what I have seen is that while a video is loading I sometimes get some jerkiness for the first 30 seconds. Otherwise, no problem and normal performance, without the CPU overrun.

 Installation on many recent distro's can be accomplished by using the supplied package manager.  On *buntu or Debian just apt-get install cpulimit. Unfortunately I don't have ready access to a Red Hat or SuSE system to verify that they have the package available.   However with the project having been around since Aug 2006, I would be surprised if it wasn't at least in one of the extra's repositories at the very least.  

Once installed I found the process to work easiest when I did the following.

  1. Start Firefox as normal.
  2. Open a terminal window
  3. ps ax | grep firefox
  4. Note the PID of the Firefox process.
  5. sudo cpulimit -l 40 -p [PID]                       # -l 40 means 40% of the max CPU.

Now surf to a youtube (or other flash) video page and try it out.  If you start top you will notice that CPU usage of the Firefox process will max out at around 40% and not go higher. 

Problem space, for me at least was that I didn't want to have to start this by hand every time I opened a Firefox window. (I don't leave my browser or any other window open if I'm not using it,  my personal habit.) Additionally I hate have to  search for the cpulimit process and close it with a kill statement every time I close Firefox.  Time to script a daemon.

The following conditions at any one time could exist.

  • Firefox is running and cpulimit is not =  We need to start cpulimit
  • Firefox   is running and cpulimit is too =  Nothing needs to be done.
  • Firefox is not running and cpulimit is running = We need to kill the cpulimit process
  • Firefox is not running and cpulimit is not running = Nothing to do.

Given the above I now know I need only test for the 1st and 3rd condition since all other possibles require no action be taken by my script.  Follows is my script as I use it.  I'll cover it's aspects later.

# Since it's a daemon put it in a while loop to keep it running.
while true; do

# check out the current PID of the running firefox and cpulimit,the extra
# grep is ugly but it gets rid of the case where grep finds itself when doing                   # a grep for the desired process. The awk strips out the PID so we can put                    # it in a variable                     
ffpid=`ps ax | grep firefox | grep -v grep | awk -F  '{ print $1 }'`
cpupid=`ps ax | grep cpulimit | grep -v grep | awk -F  '{ print $1 }'`

       #  Check to see if the PID is not a null set 

        if [ $ffpid > "0" ]; then

               # now check to see if the cpulimt process is started and if not start it.                 # Then sleep for 30 seconds.  Otherwise go to sleep       

                if [ -z $cpupid ]; then
                        sudo cpulimit -l 40 -p $ffpid &
                        sleep 30
                        sleep 30


              # If Firefox is not running (PID not > than 0) we need to check if cpulimit     

              # is   running and stop t if it is.  Then sleep for 30 seconds, if not just sleep.

               if [ $cpupid > "0" ]; then
                        sudo kill -9 $cpupid
                        sleep 30
                        sleep 30



Given the above script I need to add in the following info.   I tried using -n for the test instead of trying to see if the PID is greater than zero.  Unfortunately the result of the ps ax statement used to grab the PID is never empty so it always returns a true.   This doesn't work.  Since I know that the PID will have to be a number greater than zero I can test for that condition reliably.  

Now I called my script ffdaemon and put it in /home/bin (I've established this dir as being in my $PATH variable. ) and then chmod 755 the file to make it executable.  Now to get it to auto start when I login to my desktop, for KDE I did 

  • cd ~/.kde/Autostart
  • ln -s ~/bin/ffdaemon  ffdaemon 

Now whenever I login this daemon process is started and every 30 seconds it runs it's check.  I experimented with various times and for my system 30 seconds was fast enough to allow me to open firefox, and begin surfing, normally I'm not instantly running a video so I'm OK letting it wait 30 seconds.  Longer than that I could make it to a video first, shorter then the checks themselves became a cpu sucker. 

This is what worked for me, hopefully it's what will work for you as well.

Click Here!