scrap 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|