NOTE:This blog had a good run, but is now in retirement.
If you enjoy the content here, please support Gregory's ongoing work on the Practicing Ruby journal.

USP: Handling excessive CPU Usage within a Process

2012-03-27 01:11, written by Eric Wong

If you’ve ever had issues with a runaway process eating up CPU time and want to kill it automatically, it’s possible to use Process.{get,set}rlimit and a signal handler for SIGXCPU to accomplish this.

The following snippet of code implements an example of a CPU limiter. This self-contained example aborts itself once CPU utilization reaches 50%.

# Users of older Rubies may want to use Process::RLIMIT_CPU
# instead of :CPU in this code.

soft, hard = Process.getrlimit(:CPU)
last_update = Time.now
max_cpu_time = 5

# this signal handler runs once we've hit max_cpu_time:
trap(:XCPU) do

 # Calculate CPU utilization based on elapsed (wall clock) time
 # and max_cpu_time
 elapsed = Time.now - last_update
 cpu_usage = max_cpu_time / elapsed
 puts "CPU utilization: #{"%0.2f" % (cpu_usage * 100)}"
 if cpu_usage > 0.5 # 50%
   abort "CPU utilization exceeded 50%"
 end

 # If we're below our CPU usage threshold, install a new limit based on
 # current Process.times
 last_update = Time.now
 t = Process.times
 Process.setrlimit(:CPU, max_cpu_time + t.utime.round + t.stime.round, hard)

 # We now return to our regularly scheduled looping ...
end


# Install an initial limit for max_cpu_time using existing process times
t = Process.times
Process.setrlimit(:CPU, max_cpu_time + t.utime.round + t.stime.round, hard)

# The signal handler registered for :XCPU will run automatically
# after the CPU time hits max_cpu_time seconds
loop do
 # do something to use the CPU...
 100000.times { 1 + 1 }

 # you can change the amount of time slept to influence CPU utilization
 sleep 0.01
end

I learned this example a few years ago from reading the PulseAudio source code:

       $ git clone git://git.0pointer.de/pulseaudio
       $ $EDITOR src/daemon/cpulimit.c

GPLv3 does not cover this message, which is CC0: To the extent possible under law, Eric Wong has waived all copyright and related or neighboring rights to the contents of this message.

blog comments powered by Disqus