Class: StripMem::App
- Inherits:
-
Object
- Object
- StripMem::App
- Defined in:
- lib/stripmem/app.rb
Instance Attribute Summary collapse
-
#command ⇒ Object
readonly
Returns the value of attribute command.
-
#start_time ⇒ Object
readonly
Returns the value of attribute start_time.
Class Method Summary collapse
Instance Method Summary collapse
- #find_children ⇒ Object
-
#initialize(argv) ⇒ App
constructor
A new instance of App.
- #kill! ⇒ Object
- #processes ⇒ Object
- #ps(channel) ⇒ Object
- #run! ⇒ Object
- #spawn! ⇒ Object
- #wait_child ⇒ Object
Constructor Details
#initialize(argv) ⇒ App
Returns a new instance of App.
21 22 23 24 |
# File 'lib/stripmem/app.rb', line 21 def initialize(argv) @command = argv @start_time = Time.now end |
Instance Attribute Details
#command ⇒ Object (readonly)
Returns the value of attribute command.
26 27 28 |
# File 'lib/stripmem/app.rb', line 26 def command @command end |
#start_time ⇒ Object (readonly)
Returns the value of attribute start_time.
26 27 28 |
# File 'lib/stripmem/app.rb', line 26 def start_time @start_time end |
Class Method Details
.run!(argv) ⇒ Object
17 18 19 |
# File 'lib/stripmem/app.rb', line 17 def self.run!(argv) new(argv).run! end |
Instance Method Details
#find_children ⇒ Object
55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/stripmem/app.rb', line 55 def find_children children = `ps a -o ppid=,pid=,command=`.lines.each_with_object(Hash.new { |h,k| h[k] = [] }) { |line, h| (line =~ /(\d+) +(\d+) +(.*)/) && h[$1].push(:pid => $2, :name => $3) } parents = processes.keys while parent = parents.shift children[parent.to_s].each do |child| if child[:name] !~ /^ps / pid = child[:pid].to_i parents << pid processes[pid] ||= child[:name] end end end end |
#kill! ⇒ Object
49 50 51 52 53 |
# File 'lib/stripmem/app.rb', line 49 def kill! Process.kill('QUIT', @child.to_i) unless @child_status rescue => e puts "kill #{@child.inspect}: #{e}" end |
#processes ⇒ Object
75 76 77 |
# File 'lib/stripmem/app.rb', line 75 def processes @processes ||= { $$ => '(stripmem)' } end |
#ps(channel) ⇒ Object
69 70 71 72 73 |
# File 'lib/stripmem/app.rb', line 69 def ps(channel) ps = `ps -o pid=,rss= -p #{processes.keys.join(',')}`.lines.each_with_object({}) { |line, h| pid, rss = line.split(/\s+/) ; h[pid.to_i] = rss.to_i } offset = Time.now - start_time channel.push :offset => offset, :samples => processes.map { |pid, name| { :name => "[#{pid}] #{name}", :rss => ps[pid] } } end |
#run! ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/stripmem/app.rb', line 28 def run! @timers = [] EventMachine.run do spawn! channel = EM::Channel.new @timers = [ EM::PeriodicTimer.new(1.0) { find_children }, EM::PeriodicTimer.new(0.2) { ps(channel) }, EM::PeriodicTimer.new(1.0) { wait_child }, ] WebSocket.new(channel).run! Thread.new do Web.new(channel).run! # This doesn't return until sinatra exits. (Sinatra handles SIGINT.) kill! EM.stop exit end end kill! end |
#spawn! ⇒ Object
79 80 81 82 83 84 |
# File 'lib/stripmem/app.rb', line 79 def spawn! @child = fork do exec(*command) end processes[@child] = command.join(' ') end |
#wait_child ⇒ Object
86 87 88 89 90 91 92 |
# File 'lib/stripmem/app.rb', line 86 def wait_child if @child_status ||= Process.waitpid2(-1, Process::WNOHANG) @timers.each do |timer| timer.cancel end end end |