bleak_house 5.3 → 6
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/CHANGELOG +1 -0
- data/Manifest +0 -2
- data/README +6 -2
- data/lib/bleak_house.rb +6 -2
- data/lib/bleak_house/analyze.rb +25 -11
- data/lib/bleak_house/bleak_house.rb +2 -12
- data/lib/bleak_house/c.rb +19 -6
- metadata +3 -5
- data/lib/bleak_house/mem_logger.rb +0 -15
- data/lib/bleak_house/ruby.rb +0 -46
data/CHANGELOG
CHANGED
data/Manifest
CHANGED
@@ -12,9 +12,7 @@
|
|
12
12
|
./lib/bleak_house/c.rb
|
13
13
|
./lib/bleak_house/dispatcher.rb
|
14
14
|
./lib/bleak_house/gruff_hacks.rb
|
15
|
-
./lib/bleak_house/mem_logger.rb
|
16
15
|
./lib/bleak_house/rake_task_redefine_task.rb
|
17
|
-
./lib/bleak_house/ruby.rb
|
18
16
|
./lib/bleak_house/support_methods.rb
|
19
17
|
./lib/bleak_house.rb
|
20
18
|
./patches/gc.c.patch
|
data/README
CHANGED
@@ -7,8 +7,8 @@ A *nix operating system. Windows is not supported.
|
|
7
7
|
|
8
8
|
Gems: 'gruff', 'rmagick', 'active_support', 'RubyInline'
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
You need to compile the bleak_house patched Ruby build. In the
|
11
|
+
plugin directory:
|
12
12
|
rake ruby:build
|
13
13
|
|
14
14
|
USAGE
|
@@ -35,6 +35,10 @@ alongside a different verson of Ruby. You could try to patch your local
|
|
35
35
|
version of Ruby instead, or you could just upgrade to 1.8.6, which has
|
36
36
|
a good trackrecord of stability anyway.
|
37
37
|
|
38
|
+
FURTHER READING
|
39
|
+
|
40
|
+
Please visit: http://blog.evanweaver.com/pages/code#bleak_house
|
41
|
+
|
38
42
|
COPYRIGHT AND LICENSING
|
39
43
|
|
40
44
|
Copyright (c) 2007 Cloudburst, LLC. See the included LICENSE_AFL
|
data/lib/bleak_house.rb
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
|
2
2
|
if ENV['BLEAK_HOUSE']
|
3
3
|
|
4
|
-
|
4
|
+
# rails
|
5
|
+
require 'dispatcher'
|
5
6
|
|
7
|
+
# logger
|
8
|
+
require 'bleak_house/c'
|
6
9
|
require 'bleak_house/bleak_house'
|
7
|
-
|
10
|
+
|
11
|
+
# overrides
|
8
12
|
require 'bleak_house/dispatcher'
|
9
13
|
require 'bleak_house/action_controller'
|
10
14
|
|
data/lib/bleak_house/analyze.rb
CHANGED
@@ -20,6 +20,7 @@ class BleakHouse
|
|
20
20
|
|
21
21
|
SMOOTHNESS = ENV['SMOOTHNESS'].to_i.zero? ? 1 : ENV['SMOOTHNESS'].to_i
|
22
22
|
MEM_KEY = "memory usage"
|
23
|
+
HEAP_KEY = "heap usage"
|
23
24
|
DIR = "#{RAILS_ROOT}/log/bleak_house/"
|
24
25
|
|
25
26
|
def initialize(data, increments, name)
|
@@ -41,7 +42,12 @@ class BleakHouse
|
|
41
42
|
g.marker_font_size = 14
|
42
43
|
|
43
44
|
@data.map do |key, values|
|
44
|
-
["#{(key.to_s.empty? ? '[Unknown]' : key).gsub(/.*::/, '')} (#{
|
45
|
+
["#{(key.to_s.empty? ? '[Unknown]' : key).gsub(/.*::/, '')} (#{ if
|
46
|
+
[MEM_KEY, HEAP_KEY].include?(key)
|
47
|
+
'relative'
|
48
|
+
else
|
49
|
+
values.to_i.max
|
50
|
+
end })", values] # hax
|
45
51
|
end.sort_by do |key, values|
|
46
52
|
0 - key[/.*?([\d]+)\)$/, 1].to_i
|
47
53
|
end.each do |key, values|
|
@@ -120,22 +126,30 @@ class BleakHouse
|
|
120
126
|
|
121
127
|
# generate initial controller graph
|
122
128
|
puts "entire app"
|
129
|
+
|
123
130
|
controller_data, increments = aggregate(data, //, /^(.*?)($|\/|::::)/)
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
131
|
+
controller_data_without_specials = controller_data.dup
|
132
|
+
controller_data_without_specials.delete(MEM_KEY)
|
133
|
+
controller_data_without_specials.delete(HEAP_KEY)
|
134
|
+
[HEAP_KEY, MEM_KEY].each do |key|
|
135
|
+
# next unless controller_data[key]
|
136
|
+
scale_factor = controller_data_without_specials.values.flatten.to_i.max / controller_data[key].max.to_f * 0.8 rescue 1
|
137
|
+
controller_data[key] = controller_data[key].map{|x| (x * scale_factor).to_i }
|
129
138
|
end
|
130
139
|
Analyze.new(controller_data, increments, "objects by controller").draw
|
131
|
-
|
140
|
+
|
132
141
|
# in each controller, by action
|
133
142
|
controller_data.keys.each do |controller|
|
134
|
-
|
135
|
-
|
143
|
+
# next unless controller == HEAP_KEY
|
144
|
+
@special = [MEM_KEY, HEAP_KEY].include? controller
|
145
|
+
puts(@special ? " #{controller}" : " action for #{controller} controller")
|
136
146
|
Dir.descend(controller) do
|
137
147
|
action_data, increments = aggregate(data, /^#{controller}($|\/|::::)/, /\/(.*?)($|\/|::::)/)
|
138
|
-
Analyze.new(action_data, increments,
|
148
|
+
Analyze.new(action_data, increments, case controller
|
149
|
+
when MEM_KEY then "#{controller} in kilobytes"
|
150
|
+
when HEAP_KEY then "#{controller} in slots"
|
151
|
+
else "objects by action in /#{controller}_controller"
|
152
|
+
end).draw
|
139
153
|
|
140
154
|
# in each action, by object class
|
141
155
|
action_data.keys.each do |action|
|
@@ -146,7 +160,7 @@ class BleakHouse
|
|
146
160
|
/::::(.*)/)
|
147
161
|
Analyze.new(class_data, increments, "objects by class in /#{controller}/#{action}").draw
|
148
162
|
end
|
149
|
-
end unless @
|
163
|
+
end unless @special
|
150
164
|
|
151
165
|
end
|
152
166
|
end
|
@@ -29,16 +29,6 @@ class BleakHouse
|
|
29
29
|
WITH_SPECIALS = false
|
30
30
|
GC = true
|
31
31
|
|
32
|
-
MEMLOGGER =
|
33
|
-
|
34
|
-
require 'bleak_house/c'
|
35
|
-
warn "using C instrumentation"
|
36
|
-
CLogger.new
|
37
|
-
else
|
38
|
-
require 'bleak_house/ruby'
|
39
|
-
warn "using pure Ruby instrumentation"
|
40
|
-
warn "(build the patched binary for speed and accuracy improvements)"
|
41
|
-
RubyLogger.new
|
42
|
-
end
|
43
|
-
|
32
|
+
MEMLOGGER = CLogger.new
|
33
|
+
|
44
34
|
end
|
data/lib/bleak_house/c.rb
CHANGED
@@ -3,11 +3,16 @@ require 'rubygems'
|
|
3
3
|
require 'inline'
|
4
4
|
|
5
5
|
class BleakHouse
|
6
|
-
class CLogger
|
6
|
+
class CLogger
|
7
7
|
|
8
8
|
MAX_UNIQ_TAGS = 1536 # per frame
|
9
9
|
MAX_TAG_LENGTH = 192 # tag plus fully namespaced classname
|
10
10
|
|
11
|
+
def mem_usage
|
12
|
+
a = `ps -o vsz,rss -p #{Process.pid}`.split(/\s+/)[-2..-1].map{|el| el.to_i}
|
13
|
+
[a.first - a.last, a.last]
|
14
|
+
end
|
15
|
+
|
11
16
|
inline do |builder|
|
12
17
|
builder.include '"node.h"' # struct RNode
|
13
18
|
builder.include '"st.h"' # struct st_table
|
@@ -97,8 +102,8 @@ class BleakHouse
|
|
97
102
|
# writes a frame to a file
|
98
103
|
builder.c <<-EOC
|
99
104
|
static void
|
100
|
-
VALUE snapshot(VALUE
|
101
|
-
Check_Type(
|
105
|
+
VALUE snapshot(VALUE logfile, VALUE tag, VALUE _specials) {
|
106
|
+
Check_Type(logfile, T_STRING);
|
102
107
|
Check_Type(tag, T_STRING);
|
103
108
|
|
104
109
|
RVALUE *p, *pend;
|
@@ -106,12 +111,12 @@ class BleakHouse
|
|
106
111
|
|
107
112
|
int specials = RTEST(_specials);
|
108
113
|
|
109
|
-
FILE *obj_log = fopen(StringValueCStr(
|
114
|
+
FILE *obj_log = fopen(StringValueCStr(logfile), "r");
|
110
115
|
int is_new;
|
111
116
|
if (!(is_new = (obj_log == NULL)))
|
112
117
|
fclose(obj_log);
|
113
118
|
|
114
|
-
if ((obj_log = fopen(StringValueCStr(
|
119
|
+
if ((obj_log = fopen(StringValueCStr(logfile), "a+")) == NULL)
|
115
120
|
rb_raise(rb_eRuntimeError, "couldn't open snapshot file");
|
116
121
|
|
117
122
|
if (is_new)
|
@@ -126,6 +131,9 @@ class BleakHouse
|
|
126
131
|
char current_tag[2048];
|
127
132
|
int counts[#{MAX_UNIQ_TAGS}];
|
128
133
|
int current_pos = 0;
|
134
|
+
|
135
|
+
int filled_slots = 0;
|
136
|
+
int free_slots = 0;
|
129
137
|
|
130
138
|
int i, j;
|
131
139
|
for (i = 0; i < rb_gc_heaps_used(); i++) {
|
@@ -133,6 +141,7 @@ class BleakHouse
|
|
133
141
|
pend = p + heaps[i].limit;
|
134
142
|
for (; p < pend; p++) {
|
135
143
|
if (p->as.basic.flags) { /* always 0 for freed objects */
|
144
|
+
filled_slots ++;
|
136
145
|
sprintf(current_tag, "");
|
137
146
|
switch (TYPE(p)) {
|
138
147
|
#{RAW_TYPES.map do |type|
|
@@ -167,10 +176,14 @@ class BleakHouse
|
|
167
176
|
current_pos ++;
|
168
177
|
}
|
169
178
|
}
|
179
|
+
} else {
|
180
|
+
free_slots ++;
|
170
181
|
}
|
171
182
|
}
|
172
183
|
}
|
173
|
-
|
184
|
+
/* fprintf(obj_log, \" :\\"heap usage/ruby heaps\\": %i\\n", rb_gc_heaps_used()); */
|
185
|
+
fprintf(obj_log, \" :\\"heap usage/filled slots\\": %i\\n", filled_slots);
|
186
|
+
fprintf(obj_log, \" :\\"heap usage/free slots\\": %i\\n", free_slots);
|
174
187
|
for (j = 0; j < current_pos; j++) {
|
175
188
|
fprintf(obj_log, " :\\"%s\\": %i\\n", tags[j], counts[j]);
|
176
189
|
}
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
|
|
3
3
|
specification_version: 1
|
4
4
|
name: bleak_house
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: "
|
7
|
-
date: 2007-05-
|
6
|
+
version: "6"
|
7
|
+
date: 2007-05-12 00:00:00 -04:00
|
8
8
|
summary: BleakHouse is a Rails plugin for finding memory leaks. It tracks ObjectSpace for your entire app, and produces charts of references by controller, by action, and by object class.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -27,7 +27,7 @@ signing_key:
|
|
27
27
|
cert_chain:
|
28
28
|
post_install_message: |+
|
29
29
|
|
30
|
-
Thanks for installing Bleak House
|
30
|
+
Thanks for installing Bleak House 6.
|
31
31
|
|
32
32
|
For each Rails app you want to profile, you will need to add the following
|
33
33
|
rake task in RAILS_ROOT/lib/tasks/bleak_house_tasks.rake to be able to run
|
@@ -60,9 +60,7 @@ files:
|
|
60
60
|
- ./lib/bleak_house/c.rb
|
61
61
|
- ./lib/bleak_house/dispatcher.rb
|
62
62
|
- ./lib/bleak_house/gruff_hacks.rb
|
63
|
-
- ./lib/bleak_house/mem_logger.rb
|
64
63
|
- ./lib/bleak_house/rake_task_redefine_task.rb
|
65
|
-
- ./lib/bleak_house/ruby.rb
|
66
64
|
- ./lib/bleak_house/support_methods.rb
|
67
65
|
- ./lib/bleak_house.rb
|
68
66
|
- ./patches/gc.c.patch
|
@@ -1,15 +0,0 @@
|
|
1
|
-
|
2
|
-
class BleakHouse
|
3
|
-
class MemLogger
|
4
|
-
def snapshot
|
5
|
-
raise "abstract method; please require 'ruby' or 'c'"
|
6
|
-
end
|
7
|
-
|
8
|
-
def mem_usage
|
9
|
-
a = `ps -o vsz,rss -p #{Process.pid}`.split(/\s+/)[-2..-1].map{|el| el.to_i}
|
10
|
-
[a.first - a.last, a.last]
|
11
|
-
end
|
12
|
-
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
data/lib/bleak_house/ruby.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'yaml'
|
3
|
-
|
4
|
-
class BleakHouse
|
5
|
-
class RubyLogger < MemLogger
|
6
|
-
SWAP = :"memory usage/swap"
|
7
|
-
RSS = :"memory usage/real"
|
8
|
-
SEEN = {}
|
9
|
-
CURRENT = {}
|
10
|
-
TAGS = Hash.new(0)
|
11
|
-
|
12
|
-
def snapshot(path, tag, _specials)
|
13
|
-
CURRENT.clear
|
14
|
-
ObjectSpace.each_object do |obj|
|
15
|
-
CURRENT[obj_id = obj._bleak_house_object_id] = true
|
16
|
-
unless SEEN[obj_id]
|
17
|
-
# symbols will rapidly stabilize
|
18
|
-
SEEN[obj_id] = "#{tag}::::#{obj._bleak_house_class}".to_sym
|
19
|
-
TAGS[SEEN[obj_id]] += 1
|
20
|
-
end
|
21
|
-
end
|
22
|
-
SEEN.keys.each do |obj_id|
|
23
|
-
TAGS[SEEN.delete(obj_id)] -= 1 unless CURRENT[obj_id]
|
24
|
-
end
|
25
|
-
CURRENT.clear
|
26
|
-
|
27
|
-
TAGS[SWAP], TAGS[RSS] = mem_usage
|
28
|
-
|
29
|
-
write(path)
|
30
|
-
end
|
31
|
-
|
32
|
-
def write(path)
|
33
|
-
exists = File.exist? path
|
34
|
-
File.open(path, 'a+') do |log|
|
35
|
-
dump = YAML.dump([[Time.now.to_i, TAGS]])
|
36
|
-
log.write(exists ? dump[5..-1] : dump)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
class Object
|
44
|
-
alias :_bleak_house_object_id :object_id
|
45
|
-
alias :_bleak_house_class :class
|
46
|
-
end
|