public
Description: Phusion Passenger (mod_rails)
Homepage: http://www.modrails.com/
Clone URL: git://github.com/FooBarWidget/passenger.git
Search Repo:
Click here to lend your support to: passenger and make a donation at www.pledgie.com !
- Move misc/memory_stats.rb into bin/ and turn it into a first-class tool.

- Add 'passenger-config' for displaying Passenger information.
Hongli Lai (Phusion) (author)
Sat Apr 19 11:48:24 -0700 2008
commit  56598a64084c5eaacd33030af4cc5776baf4ce57
tree    46447f8e63b4cba25fbcc805ae2c206c393a5d3f
parent  2e06f5eecc7ed81e4e2ea39abf12834023bc5d5f
...
379
380
381
382
 
 
 
 
 
 
383
384
385
...
379
380
381
 
382
383
384
385
386
387
388
389
390
0
@@ -379,7 +379,12 @@
0
   ] - Dir['test/stub/*/log/*'] \
0
    - Dir['test/stub/*/tmp/*/*'] \
0
    - Dir['test/stub/apache2/*.{pid,lock,log}']
0
- s.executables = ['passenger-spawn-server', 'passenger-install-apache2-module']
0
+ s.executables = [
0
+ 'passenger-spawn-server',
0
+ 'passenger-install-apache2-module',
0
+ 'passenger-config',
0
+ 'passenger-memory-stats'
0
+ ]
0
   s.has_rdoc = true
0
   s.extra_rdoc_files = ['README']
0
   s.rdoc_options <<
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
0
@@ -1 +1,23 @@
0
+#!/usr/bin/env ruby
0
+PASSENGER_ROOT = File.expand_path(File.dirname(__FILE__) << "/..")
0
+
0
+def help
0
+ puts "Tool for showing Passenger configuration information."
0
+ puts "Usage: passenger-config <OPTIONS>"
0
+ puts
0
+ puts "Options:"
0
+ puts " --root Show Passenger's root directory."
0
+ puts " --version Show Passenger's version number."
0
+end
0
+
0
+case ARGV[0]
0
+when "--root"
0
+ puts PASSENGER_ROOT
0
+when "--version"
0
+ File.read("#{PASSENGER_ROOT}/Rakefile") =~ /^PACKAGE_VERSION = "(.*)"/
0
+ puts $1
0
+else
0
+ help
0
+ exit 1
0
+end
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
0
@@ -1 +1,133 @@
0
+#!/usr/bin/env ruby
0
+$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/../lib")
0
+require 'passenger/platform_info'
0
+
0
+class MemoryStats
0
+ class Process
0
+ attr_accessor :pid
0
+ attr_accessor :ppid
0
+ attr_accessor :threads
0
+ attr_accessor :vm_size # in KB
0
+ attr_accessor :name
0
+ attr_accessor :private_dirty_rss # in KB
0
+
0
+ def vm_size_in_mb
0
+ return sprintf("%.1f MB", vm_size / 1024.0)
0
+ end
0
+
0
+ def private_dirty_rss_in_mb
0
+ if private_dirty_rss.is_a?(Numeric)
0
+ return sprintf("%.1f MB", private_dirty_rss / 1024.0)
0
+ else
0
+ return "?"
0
+ end
0
+ end
0
+
0
+ def print
0
+ printf "%-6d %-6d %-6d %-9s %-9s %s\n", pid, ppid, threads,
0
+ vm_size_in_mb, private_dirty_rss_in_mb, name
0
+ end
0
+ end
0
+
0
+ def start
0
+ apache_processes = list_processes(:exe => PlatformInfo::HTTPD)
0
+ print_process_list_stats(apache_processes)
0
+
0
+ puts
0
+ passenger_processes = list_processes(:match => /(^Passenger |^Rails:|ApplicationPoolServerExecutable)/)
0
+ print_process_list_stats(passenger_processes)
0
+
0
+ if ::Process.uid != 0 && (apache_processes + passenger_processes).any?{ |p| p.private_dirty_rss.nil? }
0
+ puts
0
+ puts "*** WARNING: Please run this tool as root. Otherwise the " <<
0
+ "private dirty RSS of processes cannot be determined."
0
+ end
0
+ end
0
+
0
+ # Returns a list of Process objects that match the given search criteria.
0
+ #
0
+ # # Search by executable path.
0
+ # list_processes(:exe => '/usr/sbin/apache2')
0
+ #
0
+ # # Search by executable name.
0
+ # list_processes(:name => 'ruby1.8')
0
+ #
0
+ # # Search by process name.
0
+ # list_processes(:match => 'Passenger FrameworkSpawner')
0
+ def list_processes(options)
0
+ if options[:exe]
0
+ name = options[:exe].sub(/.*\/(.*)/, '\1')
0
+ ps = "ps -C '#{name}'"
0
+ elsif options[:name]
0
+ ps = "ps -C '#{options[:name]}'"
0
+ elsif options[:match]
0
+ ps = "ps -A"
0
+ else
0
+ raise ArgumentError, "Invalid options."
0
+ end
0
+
0
+ processes = []
0
+ list = `#{ps} -o pid,ppid,nlwp,vsz,command`.split("\n")
0
+ list.shift
0
+ list.each do |line|
0
+ line.gsub!(/^ */, '')
0
+ line.gsub!(/ *$/, '')
0
+
0
+ p = Process.new
0
+ p.pid, p.ppid, p.threads, p.vm_size, p.name = line.split(/ +/, 5)
0
+ if p.name !~ /^ps/ && (!options[:match] || p.name.match(options[:match]))
0
+ [:pid, :ppid, :threads, :vm_size].each do |attr|
0
+ p.send("#{attr}=", p.send(attr).to_i)
0
+ end
0
+ p.private_dirty_rss = determine_private_dirty_rss(p.pid)
0
+ processes << p
0
+ end
0
+ end
0
+ return processes
0
+ end
0
+
0
+private
0
+ # Returns the private dirty RSS for the given process, in KB.
0
+ def determine_private_dirty_rss(pid)
0
+ total = 0
0
+ File.read("/proc/#{pid}/smaps").split("\n").each do |line|
0
+ line =~ /^(Private)_Dirty: +(\d+)/
0
+ if $2
0
+ total += $2.to_i
0
+ end
0
+ end
0
+ return total
0
+ rescue Errno::EACCES, Errno::ENOENT
0
+ return nil
0
+ end
0
+
0
+ def print_header
0
+ puts "PID PPID Thrds VM Size Private Name"
0
+ puts "-" * 79
0
+ end
0
+
0
+ def print_process_list_stats(processes)
0
+ total_private_dirty_rss = 0
0
+ some_private_dirty_rss_cannot_be_determined = false
0
+
0
+ print_header
0
+ processes.each do |p|
0
+ if p.private_dirty_rss.is_a?(Numeric)
0
+ total_private_dirty_rss += p.private_dirty_rss
0
+ else
0
+ some_private_dirty_rss_cannot_be_determined = true
0
+ end
0
+ p.print
0
+ end
0
+ puts "### Processes: #{processes.size}"
0
+ printf "### Total private dirty RSS: %.2f MB", total_private_dirty_rss / 1024.0
0
+ if some_private_dirty_rss_cannot_be_determined
0
+ puts " (?)"
0
+ else
0
+ puts
0
+ end
0
+ end
0
+end
0
+
0
+MemoryStats.new.start
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0
@@ -1,127 +1 @@
0
-#!/usr/bin/env ruby
0
-$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/../lib")
0
-require 'passenger/platform_info'
0
-
0
-class MemoryStats
0
- class Process
0
- attr_accessor :pid
0
- attr_accessor :ppid
0
- attr_accessor :threads
0
- attr_accessor :vm_size # in KB
0
- attr_accessor :name
0
- attr_accessor :private_dirty_rss # in KB
0
-
0
- def vm_size_in_mb
0
- return sprintf("%.1f MB", vm_size / 1024.0)
0
- end
0
-
0
- def private_dirty_rss_in_mb
0
- if private_dirty_rss.is_a?(Numeric)
0
- return sprintf("%.1f MB", private_dirty_rss / 1024.0)
0
- else
0
- return "?"
0
- end
0
- end
0
-
0
- def print
0
- printf "%-6d %-6d %-6d %-9s %-9s %s\n", pid, ppid, threads,
0
- vm_size_in_mb, private_dirty_rss_in_mb, name
0
- end
0
- end
0
-
0
- def start
0
- processes = list_processes(:exe => PlatformInfo::HTTPD)
0
- print_process_list_stats(processes)
0
-
0
- puts
0
- processes = list_processes(:match => /(^Passenger |^Rails:|ApplicationPoolServerExecutable)/)
0
- print_process_list_stats(processes)
0
- end
0
-
0
- # Returns a list of Process objects that match the given search criteria.
0
- #
0
- # # Search by executable path.
0
- # list_processes(:exe => '/usr/sbin/apache2')
0
- #
0
- # # Search by executable name.
0
- # list_processes(:name => 'ruby1.8')
0
- #
0
- # # Search by process name.
0
- # list_processes(:match => 'Passenger FrameworkSpawner')
0
- def list_processes(options)
0
- if options[:exe]
0
- name = options[:exe].sub(/.*\/(.*)/, '\1')
0
- ps = "ps -C '#{name}'"
0
- elsif options[:name]
0
- ps = "ps -C '#{options[:name]}'"
0
- elsif options[:match]
0
- ps = "ps -A"
0
- else
0
- raise ArgumentError, "Invalid options."
0
- end
0
-
0
- processes = []
0
- list = `#{ps} -o pid,ppid,nlwp,vsz,command`.split("\n")
0
- list.shift
0
- list.each do |line|
0
- line.gsub!(/^ */, '')
0
- line.gsub!(/ *$/, '')
0
-
0
- p = Process.new
0
- p.pid, p.ppid, p.threads, p.vm_size, p.name = line.split(/ +/, 5)
0
- if p.name !~ /^ps/ && (!options[:match] || p.name.match(options[:match]))
0
- [:pid, :ppid, :threads, :vm_size].each do |attr|
0
- p.send("#{attr}=", p.send(attr).to_i)
0
- end
0
- p.private_dirty_rss = determine_private_dirty_rss(p.pid)
0
- processes << p
0
- end
0
- end
0
- return processes
0
- end
0
-
0
-private
0
- # Returns the private dirty RSS for the given process, in KB.
0
- def determine_private_dirty_rss(pid)
0
- total = 0
0
- File.read("/proc/#{pid}/smaps").split("\n").each do |line|
0
- line =~ /^(Private)_Dirty: +(\d+)/
0
- if $2
0
- total += $2.to_i
0
- end
0
- end
0
- return total
0
- rescue Errno::EACCES, Errno::ENOENT
0
- return nil
0
- end
0
-
0
- def print_header
0
- puts "PID PPID Thrds VM Size Private Name"
0
- puts "-" * 79
0
- end
0
-
0
- def print_process_list_stats(processes)
0
- total_private_dirty_rss = 0
0
- some_private_dirty_rss_cannot_be_determined = false
0
-
0
- print_header
0
- processes.each do |p|
0
- if p.private_dirty_rss.is_a?(Numeric)
0
- total_private_dirty_rss += p.private_dirty_rss
0
- else
0
- some_private_dirty_rss_cannot_be_determined = true
0
- end
0
- p.print
0
- end
0
- puts "### Processes: #{processes.size}"
0
- printf "### Total private dirty RSS: %.2f MB", total_private_dirty_rss / 1024.0
0
- if some_private_dirty_rss_cannot_be_determined
0
- puts " (?)"
0
- else
0
- puts
0
- end
0
- end
0
-end
0
-
0
-MemoryStats.new.start

Comments

    No one has commented yet.