scrap 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/LICENSE +19 -0
- data/README.markdown +42 -0
- data/Rakefile +1 -0
- data/config/routes.rb +3 -0
- data/lib/scrap.rb +217 -0
- data/lib/scrap/railtie.rb +7 -0
- data/lib/scrap/version.rb +3 -0
- data/sample.html +12 -0
- data/scrap.gemspec +24 -0
- data/scrap.yml.example +9 -0
- metadata +63 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2008 Chris Heald
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
Scrap is a Rack endpoint designed to expose various garbage and memory-related metrics about your app. It may be particularly useful in tracking down memory leaks or bloated actions.
|
2
|
+
|
3
|
+
For use in Rails apps: just add it to your Gemfile (if you're using bundler, which you probably are). Scrap includes a railtie that will automatically activate it.
|
4
|
+
For use in Rack apps: install the gem, require 'scrap', and run Scrap as a middleware.
|
5
|
+
|
6
|
+
Scrap will provide a new url, <code>/stats/scrap</code>, which will report a number of metrics about your app.
|
7
|
+
|
8
|
+
For an example of the output, see [TBD].
|
9
|
+
|
10
|
+
## Dependencies
|
11
|
+
|
12
|
+
None, really, though Scrap is intended for Linux systems. On OS
|
13
|
+
X, the Ruby GC statistics will be displayed, but overall process memory
|
14
|
+
usage will not be reported.
|
15
|
+
|
16
|
+
## Config
|
17
|
+
|
18
|
+
If present, Scrap will use a config/scrap.yml file. See the provided example file for a list of the configuration options accepted.
|
19
|
+
|
20
|
+
* max requests: How many requests to keep a record of. Older requests will be pushed out of the queue when the limit has been reached. Default is 150.
|
21
|
+
* max_objects: How many objects/deltas to show. Default is 50.
|
22
|
+
* classes: A hash of class names to do object counting on. Values may be "true" which prints the object count with a default set of options, or it may be a hash consisting of the following:
|
23
|
+
* print_objects: boolean - toggles the output of a representation of each instance of the type.
|
24
|
+
* show_fields: array - list of fields to show per instance. This actually invokes the "attributes" method of the object, so it's really only useful for ActiveRecord objects.
|
25
|
+
* small: boolean - if false, will not print counts in h3 tags. Default is true.
|
26
|
+
* min: integer - minimum count, if set, that an object must have to appear in the delta or top objects list. Default is nil.
|
27
|
+
|
28
|
+
## Other considerations
|
29
|
+
|
30
|
+
Scrap was originally written for Ruby 1.8.7, with lots of switches to
|
31
|
+
enable it to take advantage of REE's better GC statistics visibility.
|
32
|
+
I've rewritten the switches to allow Scrap to use 1.9.3's statistics,
|
33
|
+
though they're harder to understand than REE's.
|
34
|
+
|
35
|
+
## Contributing
|
36
|
+
|
37
|
+
Just message me! I am very happy working with more contributors,
|
38
|
+
accepting pull requests, etc. I'm very open to bug reports or feature suggestions.
|
39
|
+
|
40
|
+
## Acknowledgements
|
41
|
+
|
42
|
+
Lots of praise goes to [Chris Heald](https://github.com/cheald/) for writing the original plugin, and [Bradley Harris](https://github.com/bradley178/scrap) for making some improvements to enable Rails 3 compatibility.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/config/routes.rb
ADDED
data/lib/scrap.rb
ADDED
@@ -0,0 +1,217 @@
|
|
1
|
+
require "scrap/version"
|
2
|
+
module Scrap
|
3
|
+
|
4
|
+
class Scrap
|
5
|
+
COMMIFY_REGEX = /(\d)(?=(\d\d\d)+(?!\d))/
|
6
|
+
CRLF = "\r\n"
|
7
|
+
|
8
|
+
def initialize(app)
|
9
|
+
@@app = app
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
Scrap.call(env)
|
14
|
+
end
|
15
|
+
|
16
|
+
@@gc_stats = {}
|
17
|
+
@@last_gc_run = nil
|
18
|
+
@@last_gc_mem = nil
|
19
|
+
@@requests_processed = 0
|
20
|
+
@@request_list = []
|
21
|
+
@@alive_at = nil
|
22
|
+
@@gc_stats_enabled = nil
|
23
|
+
@@config = nil
|
24
|
+
|
25
|
+
def self.config
|
26
|
+
@@config ||= YAML::load open(File.join(Rails.root, "config", "scrap.yml")).read
|
27
|
+
rescue Errno::ENOENT
|
28
|
+
@@config = {}
|
29
|
+
rescue
|
30
|
+
puts "[scrap] scrap.yml: #{$!.message}"
|
31
|
+
@@config = {}
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.call(env)
|
35
|
+
if !@@gc_stats_enabled
|
36
|
+
GC.enable_stats if GC.respond_to? :enable_stats # for REE
|
37
|
+
GC::Profiler.enable if defined? GC::Profiler # for 1.9.3+
|
38
|
+
@@gc_stats_enabled = true
|
39
|
+
end
|
40
|
+
@@requests_processed += 1
|
41
|
+
@@last_gc_run ||= @@alive_at ||= Time.now.to_f
|
42
|
+
@@last_gc_mem ||= get_usage
|
43
|
+
|
44
|
+
req = sprintf("<p>vsize:[%-10.2fMB] rss:[%-10.2fMB] %s %s</p>", get_usage[:virtual], get_usage[:real], env["REQUEST_METHOD"], env["PATH_INFO"])
|
45
|
+
req << "<pre>#{ObjectSpace.statistics}</pre>" if ObjectSpace.respond_to? :statistics
|
46
|
+
req << "<pre>#{readable_gc_stat}</pre>" if GC.respond_to? :stat
|
47
|
+
@@request_list.unshift req
|
48
|
+
@@request_list.pop if @@request_list.length > (config["max_requests"] || 150)
|
49
|
+
|
50
|
+
if env["PATH_INFO"] == "/stats/scrap"
|
51
|
+
gc_stats
|
52
|
+
else
|
53
|
+
@@app.call(env)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.gc_stats
|
58
|
+
collected = nil
|
59
|
+
puts "Respond to? #{ObjectSpace.respond_to? :live_objects}"
|
60
|
+
if ObjectSpace.respond_to? :live_objects
|
61
|
+
live = ObjectSpace.live_objects
|
62
|
+
GC.start
|
63
|
+
collected = live - ObjectSpace.live_objects
|
64
|
+
else
|
65
|
+
GC.start
|
66
|
+
end
|
67
|
+
usage = get_usage
|
68
|
+
|
69
|
+
virtual_mem_delta = usage[:virtual] - @@last_gc_mem[:virtual]
|
70
|
+
real_mem_delta = usage[:real] - @@last_gc_mem[:real]
|
71
|
+
time_delta = Time.now.to_f - @@last_gc_run
|
72
|
+
s = ''
|
73
|
+
s << '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"' << CRLF
|
74
|
+
s << ' "http://www.w3.org/TR/html4/strict.dtd">' << CRLF
|
75
|
+
s << '<html><head>' << CRLF
|
76
|
+
s << "<title>[#{$$}] Garbage Report</title>" << CRLF
|
77
|
+
s << '<style type="text/css"> body { font-family: monospace; color: #222; } td { border-bottom: 1px solid #eee; padding: 1px 9px; } td.t { background: #fafafa; } tr:hover td { background: #fafaf0; border-color: #e0e0dd; } h1,h2,h3 { border-bottom: 1px solid #ddd; font-family: sans-serif; } </style>' << CRLF
|
78
|
+
s << '<body>' << CRLF
|
79
|
+
|
80
|
+
s << "<h1>Scrap - PID #{$$}</h1>" << CRLF
|
81
|
+
|
82
|
+
s << '<table>' << CRLF
|
83
|
+
s << sprintf('<tr><td class="t">Virtual Memory usage:</td><td>%2.2fMB</td></tr>', usage[:virtual])
|
84
|
+
s << sprintf('<tr><td class="t">Real Memory usage:</td><td>%2.2fMB</td></tr>', usage[:real])
|
85
|
+
s << sprintf('<tr><td class="t">Vsize Delta:</td><td>%2.2fMB</td></tr>', virtual_mem_delta)
|
86
|
+
s << sprintf('<tr><td class="t">RSS Delta:</td><td>%2.2fMB</td></tr>', real_mem_delta)
|
87
|
+
s << sprintf('<tr><td class="t">Last Scrap req:</td><td>%2.2f seconds ago</td></tr>', time_delta)
|
88
|
+
s << sprintf('<tr><td class="t">Requests processed:</td><td>%s</td></tr>', @@requests_processed)
|
89
|
+
s << sprintf('<tr><td class="t">Alive for:</td><td>%2.2f seconds</td></tr>', Time.now.to_f - @@alive_at)
|
90
|
+
if GC.respond_to? :time
|
91
|
+
s << sprintf('<tr><td class="t">Total time spent in GC:</td><td>%2.2f seconds</td></tr>', GC.time / 1000000.0)
|
92
|
+
elsif defined? GC::Profiler
|
93
|
+
s << sprintf('<tr><td class="t">Total time spent in GC:</td><td>%2.2f seconds</td></tr>', GC::Profiler.total_time / 1000.0)
|
94
|
+
end
|
95
|
+
if collected
|
96
|
+
s << sprintf('<tr><td class="t">Collected objects:</td><td>%2d</td></tr>', collected)
|
97
|
+
s << sprintf('<tr><td class="t">Live objects:</td><td>%2d</td></tr>', ObjectSpace.live_objects)
|
98
|
+
end
|
99
|
+
s << '</table>' << CRLF
|
100
|
+
|
101
|
+
s << "<h3>Top #{config["max_objects"]} deltas since last request</h3>"
|
102
|
+
s << '<table border="0">'
|
103
|
+
memcheck(config["max_objects"], Object, :deltas).each do |v|
|
104
|
+
next if v.last == 0
|
105
|
+
s << "<tr><td class='t'>#{v.first}</td><td>#{sprintf("%s%s", v.last >= 0 ? "+" : "-", commify(v.last))}</td></tr>"
|
106
|
+
end
|
107
|
+
s << '</table>'
|
108
|
+
|
109
|
+
s << "<h3>Top #{config["max_objects"]} objects</h3>"
|
110
|
+
s << '<table border="0">'
|
111
|
+
memcheck(config["max_objects"]).each do |v|
|
112
|
+
s << "<tr><td class='t'>#{v.first}</td><td>#{commify v.last}</td></tr>"
|
113
|
+
end
|
114
|
+
s << '</table>'
|
115
|
+
|
116
|
+
(config["classes"] || {}).each do |klass, val|
|
117
|
+
puts val.inspect
|
118
|
+
opts = val === true ? {"print_objects" => true} : val
|
119
|
+
add_os(klass.constantize, s, opts)
|
120
|
+
end
|
121
|
+
|
122
|
+
s << '<h3>Request history</h3>'
|
123
|
+
@@request_list.each do |req|
|
124
|
+
s << req
|
125
|
+
end
|
126
|
+
s << '</body></html>'
|
127
|
+
|
128
|
+
@@last_gc_run = Time.now.to_f
|
129
|
+
@@last_gc_mem = usage
|
130
|
+
@@requests_processed = 0
|
131
|
+
[200, {"Content-Type" => "text/html"}, [s]]
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.get_usage
|
135
|
+
usage = Hash.new("N/A")
|
136
|
+
begin
|
137
|
+
stat = `cat /proc/#{$$}/stat`.split(" ")
|
138
|
+
usage[:virtual] = stat[22].to_i / (1024 * 1024).to_f
|
139
|
+
usage[:real] = stat[23].to_i * (`getconf PAGESIZE`.to_f) / (1024 * 1024).to_f
|
140
|
+
rescue
|
141
|
+
# pass
|
142
|
+
end
|
143
|
+
return usage
|
144
|
+
end
|
145
|
+
|
146
|
+
def self.add_os(c, s, options = {})
|
147
|
+
print_objects = options["print_objects"]
|
148
|
+
small = options["small"]
|
149
|
+
min = options["min"]
|
150
|
+
show_fields = options["show_fields"]
|
151
|
+
|
152
|
+
ct = ObjectSpace.each_object(c) {}
|
153
|
+
return if min and ct < min
|
154
|
+
|
155
|
+
if small
|
156
|
+
s << "#{c} (#{ct})<br />"
|
157
|
+
else
|
158
|
+
s << "<h3>#{c} (#{ct})</h3>"
|
159
|
+
end
|
160
|
+
|
161
|
+
return if !print_objects or ct == 0
|
162
|
+
s << CRLF
|
163
|
+
s << '<table>'
|
164
|
+
val = ObjectSpace.each_object(c) do |m|
|
165
|
+
s << '<tr><td class="t">' << "<#{m.class.to_s}:#{sprintf("0x%.8x", m.object_id)}></td>"
|
166
|
+
if show_fields then
|
167
|
+
show_fields.each do |field|
|
168
|
+
v = m.attributes[field.to_s]
|
169
|
+
if v.blank?
|
170
|
+
s << '<td> </td>'
|
171
|
+
else
|
172
|
+
s << "<td>#{field}: #{v}</td>"
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
s << '</tr>'
|
177
|
+
end
|
178
|
+
s << '</table>' << CRLF
|
179
|
+
end
|
180
|
+
|
181
|
+
def self.memcheck(top, klass = Object, mode = :normal)
|
182
|
+
top ||= 50
|
183
|
+
os = Hash.new(0)
|
184
|
+
ObjectSpace.each_object(klass) do |o|
|
185
|
+
begin;
|
186
|
+
# If this is true, it's an association proxy, and we don't want to invoke method_missing on it,
|
187
|
+
# as it will result in a load of the association proxy from the DB, doing extra DB work and
|
188
|
+
# potentially creating a lot of AR objects. Hackalicious.
|
189
|
+
next if o.respond_to? :proxy_respond_to?
|
190
|
+
os[o.class.to_s] += 1 if o.respond_to? :class
|
191
|
+
rescue; end
|
192
|
+
end
|
193
|
+
if mode == :deltas then
|
194
|
+
os2 = Hash.new(0)
|
195
|
+
os.each do |k, v|
|
196
|
+
os2[k] = v - (@@gc_stats[k] || 0)
|
197
|
+
@@gc_stats[k] = v
|
198
|
+
end
|
199
|
+
sorted = os2.sort_by{|k,v| -v }.first(top)
|
200
|
+
else
|
201
|
+
sorted = os.sort_by{|k,v| -v }.first(top)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def self.readable_gc_stat
|
206
|
+
stat = GC.stat
|
207
|
+
"GC cycles so far: #{stat[:count]}\nNumber of heaps : #{stat[:heap_used]}\nNumber of objects : #{ObjectSpace.count_objects[:TOTAL]}\nHeap length : #{stat[:heap_length]}\nHeap increment : #{stat[:heap_increment]}\nHeap live num : #{stat[:heap_live_num]}\nHeap free num : #{stat[:heap_free_num]}\nHeap final num : #{stat[:heap_final_num]}\n"
|
208
|
+
end
|
209
|
+
|
210
|
+
def self.commify(i)
|
211
|
+
i.to_s.gsub(COMMIFY_REGEX, "\\1,")
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
require "scrap/railtie" if defined? Rails
|
216
|
+
|
217
|
+
end
|
data/sample.html
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
<html><head>
|
2
|
+
<meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>[9752] Garbage Report</title><style> body { font-family: monospace; color: #222; } td { border-bottom: 1px solid #eee; padding: 1px 9px; } td.t { background: #fafafa; } tr:hover td { background: #fafaf0; border-color: #e0e0dd; } h1,h2,h3 { border-bottom: 1px solid #ddd; font-family: sans-serif; } </style></head><body><h1>Scrap - PID 9752</h1><table><tbody><tr><td class="t">Memory usage:</td><td>59.01MB</td></tr><tr><td class="t">Delta:</td><td>0.00MB</td></tr><tr><td class="t">Last Scrap req:</td><td>0.39 seconds ago</td></tr><tr><td class="t">Requests processed:</td><td>1</td></tr><tr><td class="t">Alive for:</td><td>0.39 seconds</td></tr><tr><td class="t">Time spent in GC:</td><td>0.18 seconds</td></tr><tr><td class="t">Collected objects:</td><td>309826</td></tr><tr><td class="t">Live objects:</td><td>696773</td></tr></tbody></table><h3>Top deltas since last request</h3><table border="0"><tbody><tr><td class="t">String</td><td>+153,220</td></tr><tr><td class="t">Array</td><td>+5,690</td></tr><tr><td class="t">Proc</td><td>+3,268</td></tr><tr><td class="t">Hash</td><td>+3,090</td></tr><tr><td class="t">Regexp</td><td>+1,978</td></tr><tr><td class="t">Class</td><td>+1,362</td></tr><tr><td class="t">ActionController::Routing::DividerSegment</td><td>+946</td></tr><tr><td class="t">ActiveSupport::Callbacks::Callback</td><td>+754</td></tr><tr><td class="t">ActionController::Routing::StaticSegment</td><td>+604</td></tr><tr><td class="t">Module</td><td>+563</td></tr><tr><td class="t">Gem::Version</td><td>+425</td></tr><tr><td class="t">Gem::Requirement</td><td>+389</td></tr><tr><td class="t">ActionController::Routing::Route</td><td>+305</td></tr><tr><td class="t">ActionController::Routing::DynamicSegment</td><td>+258</td></tr><tr><td class="t">ActionController::Routing::OptionalFormatSegment</td><td>+223</td></tr><tr><td class="t">ActiveSupport::Callbacks::CallbackChain</td><td>+218</td></tr><tr><td class="t">Range</td><td>+190</td></tr><tr><td class="t">ActiveRecord::Reflection::AssociationReflection</td><td>+142</td></tr><tr><td class="t">Time</td><td>+132</td></tr><tr><td class="t">Gem::Specification</td><td>+128</td></tr><tr><td class="t">Gem::Dependency</td><td>+120</td></tr><tr><td class="t">Float</td><td>+103</td></tr><tr><td class="t">UnboundMethod</td><td>+98</td></tr><tr><td class="t">Magick::CompositeOperator</td><td>+56</td></tr><tr><td class="t">Set</td><td>+34</td></tr><tr><td class="t">Magick::PreviewType</td><td>+30</td></tr><tr><td class="t">HashWithIndifferentAccess</td><td>+24</td></tr><tr><td class="t">Magick::ColorspaceType</td><td>+23</td></tr><tr><td class="t">Magick::FilterTypes</td><td>+22</td></tr><tr><td class="t">Mime::Type</td><td>+21</td></tr><tr><td class="t">ActiveRecord::Reflection::ThroughReflection</td><td>+19</td></tr><tr><td class="t">Magick::ChannelType</td><td>+18</td></tr><tr><td class="t">Magick::ImageLayerMethod</td><td>+16</td></tr><tr><td class="t">Rails::Plugin</td><td>+15</td></tr><tr><td class="t">Rails::OrderedOptions</td><td>+14</td></tr><tr><td class="t">Magick::VirtualPixelMethod</td><td>+13</td></tr><tr><td class="t">Magick::GravityType</td><td>+12</td></tr><tr><td class="t">Magick::QuantumExpressionOperator</td><td>+12</td></tr><tr><td class="t">ActionController::MiddlewareStack::Middleware</td><td>+12</td></tr><tr><td class="t">Magick::ImageType</td><td>+12</td></tr><tr><td class="t">Mutex</td><td>+12</td></tr><tr><td class="t">Rails::GemDependency</td><td>+11</td></tr><tr><td class="t">Rails::GemPlugin</td><td>+11</td></tr><tr><td class="t">Magick::CompressionType</td><td>+11</td></tr><tr><td class="t">Magick::StretchType</td><td>+10</td></tr><tr><td class="t">Bignum</td><td>+9</td></tr><tr><td class="t">Magick::OrientationType</td><td>+9</td></tr><tr><td class="t">ThinkingSphinx::Index::FauxColumn</td><td>+9</td></tr><tr><td class="t">Magick::InterlaceType</td><td>+8</td></tr><tr><td class="t">Magick::DistortImageMethod</td><td>+8</td></tr></tbody></table><h3>Top objects</h3><table border="0"><tbody><tr><td class="t">String</td><td>111,167</td></tr><tr><td class="t">Array</td><td>5,860</td></tr><tr><td class="t">Proc</td><td>3,268</td></tr><tr><td class="t">Hash</td><td>3,091</td></tr><tr><td class="t">Regexp</td><td>1,978</td></tr><tr><td class="t">Class</td><td>1,362</td></tr><tr><td class="t">ActionController::Routing::DividerSegment</td><td>946</td></tr><tr><td class="t">ActiveSupport::Callbacks::Callback</td><td>754</td></tr><tr><td class="t">ActionController::Routing::StaticSegment</td><td>604</td></tr><tr><td class="t">Module</td><td>563</td></tr><tr><td class="t">Gem::Version</td><td>425</td></tr><tr><td class="t">Gem::Requirement</td><td>389</td></tr><tr><td class="t">ActionController::Routing::Route</td><td>305</td></tr><tr><td class="t">ActionController::Routing::DynamicSegment</td><td>258</td></tr><tr><td class="t">ActionController::Routing::OptionalFormatSegment</td><td>223</td></tr><tr><td class="t">ActiveSupport::Callbacks::CallbackChain</td><td>218</td></tr><tr><td class="t">Range</td><td>190</td></tr><tr><td class="t">ActiveRecord::Reflection::AssociationReflection</td><td>142</td></tr><tr><td class="t">Time</td><td>130</td></tr><tr><td class="t">Gem::Specification</td><td>128</td></tr><tr><td class="t">Gem::Dependency</td><td>120</td></tr><tr><td class="t">UnboundMethod</td><td>98</td></tr><tr><td class="t">Float</td><td>94</td></tr><tr><td class="t">Magick::CompositeOperator</td><td>56</td></tr><tr><td class="t">Set</td><td>34</td></tr><tr><td class="t">Magick::PreviewType</td><td>30</td></tr><tr><td class="t">HashWithIndifferentAccess</td><td>24</td></tr><tr><td class="t">Magick::ColorspaceType</td><td>23</td></tr><tr><td class="t">Magick::FilterTypes</td><td>22</td></tr><tr><td class="t">Mime::Type</td><td>21</td></tr><tr><td class="t">ActiveRecord::Reflection::ThroughReflection</td><td>19</td></tr><tr><td class="t">Magick::ChannelType</td><td>18</td></tr><tr><td class="t">Magick::ImageLayerMethod</td><td>16</td></tr><tr><td class="t">Rails::Plugin</td><td>15</td></tr><tr><td class="t">Rails::OrderedOptions</td><td>14</td></tr><tr><td class="t">Magick::VirtualPixelMethod</td><td>13</td></tr><tr><td class="t">Magick::QuantumExpressionOperator</td><td>12</td></tr><tr><td class="t">Mutex</td><td>12</td></tr><tr><td class="t">ActionController::MiddlewareStack::Middleware</td><td>12</td></tr><tr><td class="t">Magick::ImageType</td><td>12</td></tr><tr><td class="t">Magick::GravityType</td><td>12</td></tr><tr><td class="t">Rails::GemDependency</td><td>11</td></tr><tr><td class="t">Magick::CompressionType</td><td>11</td></tr><tr><td class="t">Rails::GemPlugin</td><td>11</td></tr><tr><td class="t">Magick::StretchType</td><td>10</td></tr><tr><td class="t">Magick::OrientationType</td><td>9</td></tr><tr><td class="t">Bignum</td><td>9</td></tr><tr><td class="t">ThinkingSphinx::Index::FauxColumn</td><td>9</td></tr><tr><td class="t">Magick::MetricType</td><td>8</td></tr><tr><td class="t">Magick::StorageType</td><td>8</td></tr></tbody></table><h3>Request history</h3>[59.01 MB] GET /stats/scrap<pre>Number of objects : 824154 (612748 AST nodes, 74.35%)
|
3
|
+
Heap slot size : 20
|
4
|
+
GC cycles so far : 26
|
5
|
+
Number of heaps : 7
|
6
|
+
Total size of objects: 16096.76 KB
|
7
|
+
Total size of heaps : 18036.66 KB (1939.91 KB = 10.76% unused)
|
8
|
+
Leading free slots : 13649 (266.58 KB = 1.48%)
|
9
|
+
Trailing free slots : 0 (0.00 KB = 0.00%)
|
10
|
+
Number of contiguous groups of 16 slots: 2113 (3.66%)
|
11
|
+
Number of terminal objects: 3890 (0.42%)
|
12
|
+
</pre><br></body></html>
|
data/scrap.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "scrap/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "scrap"
|
7
|
+
s.version = Scrap::VERSION
|
8
|
+
s.authors = ["Chris Heald", "Bradley Harris", "Ben Somers", "Joseph Chen"]
|
9
|
+
s.email = ["joseph.chen@gmail.com", "somers.ben@gmail.com"]
|
10
|
+
s.homepage = "http://www.github.com/bensomers/scrap"
|
11
|
+
s.summary = %q{Scrap is a Rack endpoint designed to expose various garbage and memory-related metrics about your app. Intended for tracking down memory leaks and bloat.}
|
12
|
+
s.description = %q{Scrap is a Rack endpoint designed to expose various garbage and memory-related metrics about your app. Intended for tracking down memory leaks and bloat.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "scrap"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
# s.add_development_dependency "rspec"
|
23
|
+
# s.add_runtime_dependency "rest-client"
|
24
|
+
end
|
data/scrap.yml.example
ADDED
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: scrap
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Chris Heald
|
9
|
+
- Bradley Harris
|
10
|
+
- Ben Somers
|
11
|
+
- Joseph Chen
|
12
|
+
autorequire:
|
13
|
+
bindir: bin
|
14
|
+
cert_chain: []
|
15
|
+
date: 2012-09-12 00:00:00.000000000 Z
|
16
|
+
dependencies: []
|
17
|
+
description: Scrap is a Rack endpoint designed to expose various garbage and memory-related
|
18
|
+
metrics about your app. Intended for tracking down memory leaks and bloat.
|
19
|
+
email:
|
20
|
+
- joseph.chen@gmail.com
|
21
|
+
- somers.ben@gmail.com
|
22
|
+
executables: []
|
23
|
+
extensions: []
|
24
|
+
extra_rdoc_files: []
|
25
|
+
files:
|
26
|
+
- .gitignore
|
27
|
+
- Gemfile
|
28
|
+
- LICENSE
|
29
|
+
- README.markdown
|
30
|
+
- Rakefile
|
31
|
+
- config/routes.rb
|
32
|
+
- lib/scrap.rb
|
33
|
+
- lib/scrap/railtie.rb
|
34
|
+
- lib/scrap/version.rb
|
35
|
+
- sample.html
|
36
|
+
- scrap.gemspec
|
37
|
+
- scrap.yml.example
|
38
|
+
homepage: http://www.github.com/bensomers/scrap
|
39
|
+
licenses: []
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
47
|
+
- - ! '>='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
requirements: []
|
57
|
+
rubyforge_project: scrap
|
58
|
+
rubygems_version: 1.8.17
|
59
|
+
signing_key:
|
60
|
+
specification_version: 3
|
61
|
+
summary: Scrap is a Rack endpoint designed to expose various garbage and memory-related
|
62
|
+
metrics about your app. Intended for tracking down memory leaks and bloat.
|
63
|
+
test_files: []
|