Created
November 18, 2010 23:12
-
-
Save robotarmy/705861 to your computer and use it in GitHub Desktop.
simple effective
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MemoryWatch | |
attr_accessor :watch_string,:high_water_pids,:callback,:high_water_mb,:delay,:num_cycles,:num_over_marks,:pids | |
def initialize(options) | |
self.callback = options[:callback] || lambda {|pid| p pid} | |
self.watch_string = (options[:watch] || "this poem is a pomme").strip | |
self.delay = options[:delay] || 60 | |
self.num_cycles = options[:num_cycles] || 3 | |
self.num_over_marks = options[:num_over_marks] || 2 | |
self.high_water_mb = options[:high_water_mb] || 700 | |
self.high_water_pids = {} | |
end | |
public | |
def cycle | |
1.upto self.num_cycles do | |
_check_pids | |
sleep self.delay | |
end | |
_trigger_callback | |
end | |
private | |
def _trigger_callback | |
self.high_water_pids.each do |pid,over_marks| | |
if over_marks.size >= self.num_over_marks | |
self.callback.call(pid) | |
end | |
end | |
end | |
def _run | |
p cmd = "ps x | grep '#{self.watch_string}' | awk '{print $1}'" | |
pids2 = %x{#{cmd}}.split() | |
pids1 = %x{#{cmd}}.split() | |
# remove the ps pid | |
self.pids = pids1 & pids2 | |
self.pids | |
end | |
def _check_pids | |
_run.each { |pid| | |
p memory_usage = %x{ps -o rss= -p #{pid}}.to_i # KB | |
if memory_usage > self.high_water_mb * 1024 # 750MB | |
puts "WARNING - Process #{pid} hit high water mark" | |
self.high_water_pids[pid] ||= [] | |
self.high_water_pids[pid] << memory_usage | |
end | |
} | |
end | |
end | |
if __FILE__ == $0 | |
require 'optparse' | |
options = {} | |
OptionParser.new do |opts| | |
opts.banner = "Usage: #{__FILE__} [options]" | |
opts.on("--callback rubycode",String, "ruby code to exectute - has \#{pid} avalible") do |v| | |
options[:callback] = lambda {|pid| # may be evil | |
eval(v) | |
} | |
end | |
opts.on("--num_over_marks N",String, "how many times the proces memory must go over to be a candidate") do |v| | |
options[:num_over_marks] = v.to_i | |
end | |
opts.on("--high_water_mb N", "the number of megabytes to be considered 'too much'") do |v| | |
options[:high_water_mb] = v.to_i | |
end | |
opts.on("--watch S",String, "process identifying string") do |v| | |
options[:watch] = v | |
end | |
opts.on("--num_cycles N", "total executions before exit") do |v| | |
options[:num_cycles] = v.to_i | |
end | |
opts.on("--delay F",Float, "delay between cycles") do |v| | |
options[:delay] = v | |
end | |
end.parse! | |
MemoryWatch.new(options).cycle | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment