bleak_house 6 → 7

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,6 +1,7 @@
1
1
 
2
2
  BleakHouse Changelog
3
3
 
4
+ 7. detect if core keys are present or not; fixes for analyzing non-rails apps
4
5
  6. log heap usage, remove pure-ruby profiler
5
6
  5.3. subtract rails core counts from action counts and convolve
6
7
  5.2. change smoothing algorithm to be more intuitive and so mem usage is correct
data/Rakefile CHANGED
@@ -15,7 +15,7 @@ begin
15
15
  VERS = `cat CHANGELOG`[/^([\d\.]+)\. /, 1]
16
16
 
17
17
  taskmsg = File.open(DIR + "/tasks/bleak_house_tasks.rake").readlines
18
- taskmsg = taskmsg[0..3] + [taskmsg[7][2..-1]] + taskmsg[9..-1]
18
+ taskmsg = taskmsg[0..3] + [taskmsg[9][2..-1]] + taskmsg[12..-1]
19
19
 
20
20
  echoe = Echoe.new("bleak_house", VERS) do |p|
21
21
  p.author = "Evan Weaver"
@@ -35,9 +35,9 @@ begin
35
35
  "
36
36
  Thanks for installing Bleak House #{VERS}.
37
37
 
38
- For each Rails app you want to profile, you will need to add the following
39
- rake task in RAILS_ROOT/lib/tasks/bleak_house_tasks.rake to be able to run
40
- the analyzer:
38
+ For each Rails app you want to profile, you will need to add the
39
+ following rake task in RAILS_ROOT/lib/tasks/bleak_house_tasks.rake
40
+ to be able to run the analyzer:
41
41
  " + taskmsg.join(" ") + "\n"}
42
42
  end
43
43
 
@@ -11,6 +11,7 @@ require 'gruff'
11
11
  load "#{File.dirname(__FILE__)}/gruff_hacks.rb"
12
12
  load "#{File.dirname(__FILE__)}/support_methods.rb"
13
13
 
14
+ Gruff::Base.send(:remove_const, "LEFT_MARGIN") # silence a warning
14
15
  Gruff::Base::LEFT_MARGIN = 200
15
16
  Gruff::Base::NEGATIVE_TOP_MARGIN = 30
16
17
  Gruff::Base::MAX_LEGENDS = 28
@@ -21,7 +22,7 @@ class BleakHouse
21
22
  SMOOTHNESS = ENV['SMOOTHNESS'].to_i.zero? ? 1 : ENV['SMOOTHNESS'].to_i
22
23
  MEM_KEY = "memory usage"
23
24
  HEAP_KEY = "heap usage"
24
- DIR = "#{RAILS_ROOT}/log/bleak_house/"
25
+ CORE_KEY = "core rails"
25
26
 
26
27
  def initialize(data, increments, name)
27
28
  @data = data
@@ -92,23 +93,31 @@ class BleakHouse
92
93
  unless File.exists? filename
93
94
  puts "No data file found: #{filename}"
94
95
  exit
95
- end
96
- FileUtils.rm_r(DIR) rescue nil
97
- Dir.mkdir(DIR)
98
-
99
- Dir.chdir(DIR) do
100
-
101
- puts "parsing data"
102
- data = YAML.load_file(filename)
103
-
104
- # subtract core counts from action
105
- data = data[0..(-1 - data.size % 2)]
106
- data = data.in_groups_of(2).map do |frames|
107
- core, action = frames.first, frames.last
108
- action.data.each do |key, value|
109
- action.data[key] = value - core.data[key[/::::(.*)/,1]].to_i
110
- end
111
- [action.time, core.data.merge(action.data)]
96
+ end
97
+ puts "parsing data"
98
+ data = YAML.load_file(filename)
99
+
100
+ rootdir = File.dirname(filename) + "/bleak_house/"
101
+ FileUtils.rm_r(rootdir) rescue nil
102
+ Dir.mkdir(rootdir)
103
+ Dir.chdir(rootdir) do
104
+
105
+ labels = ["controller", "action"]
106
+ # autodetect need for rails snapshot conflation
107
+ if data.first.last.keys.first =~ /^#{CORE_KEY}::::/
108
+ # subtract core counts from action
109
+ data = data[0..(-1 - data.size % 2)]
110
+ data = data.in_groups_of(2).map do |frames|
111
+ core, action = frames.first, frames.last
112
+ action.data.each do |key, value|
113
+ action.data[key] = value - core.data[key[/::::(.*)/,1]].to_i
114
+ end
115
+ [action.time, core.data.merge(action.data)]
116
+ end
117
+ puts " conflated core rails snapshots with their actions"
118
+ else
119
+ puts " assuming custom snapshotting"
120
+ labels = ["tag", "subtag"]
112
121
  end
113
122
 
114
123
  # smooth
@@ -122,45 +131,48 @@ class BleakHouse
122
131
  end
123
132
  [Time.at(timestamp).strftime("%H:%M:%S"), values]
124
133
  end
125
- puts "#{data.size} frames after smoothing"
126
-
127
- # generate initial controller graph
128
- puts "entire app"
134
+ puts " #{data.size} frames after smoothing"
129
135
 
136
+ # scale memory/heap frames
130
137
  controller_data, increments = aggregate(data, //, /^(.*?)($|\/|::::)/)
131
138
  controller_data_without_specials = controller_data.dup
132
139
  controller_data_without_specials.delete(MEM_KEY)
133
140
  controller_data_without_specials.delete(HEAP_KEY)
134
141
  [HEAP_KEY, MEM_KEY].each do |key|
135
- # next unless controller_data[key]
136
142
  scale_factor = controller_data_without_specials.values.flatten.to_i.max / controller_data[key].max.to_f * 0.8 rescue 1
137
143
  controller_data[key] = controller_data[key].map{|x| (x * scale_factor).to_i }
138
144
  end
139
- Analyze.new(controller_data, increments, "objects by controller").draw
145
+
146
+ # generate initial controller graph
147
+ puts(title = "objects by #{labels[0]}")
148
+ Analyze.new(controller_data, increments, title).draw
140
149
 
141
150
  # in each controller, by action
142
151
  controller_data.keys.each do |controller|
143
152
  # next unless controller == HEAP_KEY
144
- @special = [MEM_KEY, HEAP_KEY].include? controller
145
- puts(@special ? " #{controller}" : " action for #{controller} controller")
153
+ @mem = [MEM_KEY, HEAP_KEY].include? controller
154
+ @core = [CORE_KEY].include? controller
146
155
  Dir.descend(controller) do
147
156
  action_data, increments = aggregate(data, /^#{controller}($|\/|::::)/, /\/(.*?)($|\/|::::)/)
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
153
-
157
+ unless @core
158
+ puts(" " + (title = case controller
159
+ when MEM_KEY then "#{controller} in kilobytes"
160
+ when HEAP_KEY then "#{controller} in slots"
161
+ else "objects by #{labels[1]} in /#{controller}/"
162
+ end))
163
+ Analyze.new(action_data, increments, title).draw
164
+ end
165
+
154
166
  # in each action, by object class
155
167
  action_data.keys.each do |action|
156
168
  action = "unknown" if action.to_s == ""
157
- puts " class for #{action} action"
158
- Dir.descend(action) do
169
+ Dir.descend(@core ? "." : action) do
170
+ puts((@core ? " " : " ") + (title = "objects by class in #{@core ? CORE_KEY : "/#{controller}/#{action}"}"))
159
171
  class_data, increments = aggregate(data, /^#{controller}#{"\/#{action}" unless action == "unknown"}($|\/|::::)/,
160
172
  /::::(.*)/)
161
- Analyze.new(class_data, increments, "objects by class in /#{controller}/#{action}").draw
173
+ Analyze.new(class_data, increments, title).draw
162
174
  end
163
- end unless @special
175
+ end unless @mem
164
176
 
165
177
  end
166
178
  end
@@ -27,8 +27,6 @@ class BleakHouse
27
27
  end
28
28
 
29
29
  WITH_SPECIALS = false
30
- GC = true
31
-
32
- MEMLOGGER = CLogger.new
33
-
30
+
31
+ MEMLOGGER = CLogger.new
34
32
  end
@@ -181,17 +181,21 @@ class BleakHouse
181
181
  }
182
182
  }
183
183
  }
184
- /* fprintf(obj_log, \" :\\"heap usage/ruby heaps\\": %i\\n", rb_gc_heaps_used()); */
185
184
  fprintf(obj_log, \" :\\"heap usage/filled slots\\": %i\\n", filled_slots);
186
185
  fprintf(obj_log, \" :\\"heap usage/free slots\\": %i\\n", free_slots);
187
186
  for (j = 0; j < current_pos; j++) {
188
187
  fprintf(obj_log, " :\\"%s\\": %i\\n", tags[j], counts[j]);
189
188
  }
190
189
  fclose(obj_log);
190
+
191
+ /* request GC run */
192
+ rb_funcall(rb_mGC, rb_intern("start"), 0);
193
+ /* to get a custom module: rb_const_get(parentModule, "ModuleName")
194
+ parent module can be something like rb_mKernel for the toplevel */
191
195
  return Qtrue;
192
196
  }
193
197
  EOC
194
198
  end
195
199
 
196
200
  end
197
- end
201
+ end
@@ -6,13 +6,11 @@ class Dispatcher
6
6
  def prepare_application_with_bleak_house
7
7
  prepare_application_without_bleak_house
8
8
  BleakHouse::MEMLOGGER.snapshot(BleakHouse::LOGFILE, 'core rails', BleakHouse::WITH_SPECIALS)
9
- GC.start if BleakHouse::GC
10
9
  end
11
10
  alias_method_chain :prepare_application, :bleak_house
12
11
 
13
12
  def reset_after_dispatch_with_bleak_house
14
13
  BleakHouse::MEMLOGGER.snapshot(BleakHouse::LOGFILE, BleakHouse.last_request_name || 'unknown', BleakHouse::WITH_SPECIALS)
15
- GC.start if BleakHouse::GC
16
14
  reset_after_dispatch_without_bleak_house
17
15
  end
18
16
  alias_method_chain :reset_after_dispatch, :bleak_house
@@ -15,7 +15,7 @@ class Gruff::Base
15
15
  @legend_labels.each_with_index do |legend_label, index|
16
16
 
17
17
  next if index > MAX_LEGENDS
18
- legend_label = "Some not shown" if index == MAX_LEGENDS
18
+ legend_label = "some not shown" if index == MAX_LEGENDS
19
19
 
20
20
  # Draw label
21
21
  @d.fill = @font_color
@@ -3,10 +3,12 @@ namespace :bleak_house do
3
3
  desc 'Analyze and chart all data'
4
4
  task :analyze do
5
5
  begin
6
- gem 'gruff', '= 0.2.8'
6
+ gem 'gruff', '= 0.2.8' # fail early if gruff is missing
7
7
  require "#{File.dirname(__FILE__)}/../lib/bleak_house/analyze"
8
+ puts "loaded vendor/plugins version"
8
9
  rescue LoadError
9
10
  require 'bleak_house/analyze'
11
+ puts "loaded gem version"
10
12
  end
11
13
  BleakHouse::Analyze.build_all("#{RAILS_ROOT}/log/bleak_house_#{RAILS_ENV}.yaml.log")
12
14
  end
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: "6"
7
- date: 2007-05-12 00:00:00 -04:00
6
+ version: "7"
7
+ date: 2007-05-13 00:00:00 -07: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,17 +27,16 @@ signing_key:
27
27
  cert_chain:
28
28
  post_install_message: |+
29
29
 
30
- Thanks for installing Bleak House 6.
30
+ Thanks for installing Bleak House 7.
31
31
 
32
- For each Rails app you want to profile, you will need to add the following
33
- rake task in RAILS_ROOT/lib/tasks/bleak_house_tasks.rake to be able to run
34
- the analyzer:
32
+ For each Rails app you want to profile, you will need to add the
33
+ following rake task in RAILS_ROOT/lib/tasks/bleak_house_tasks.rake
34
+ to be able to run the analyzer:
35
35
 
36
36
  namespace :bleak_house do
37
37
  desc 'Analyze and chart all data'
38
38
  task :analyze do
39
- rescue LoadError
40
- end
39
+ require 'bleak_house/analyze'
41
40
  BleakHouse::Analyze.build_all("#{RAILS_ROOT}/log/bleak_house_#{RAILS_ENV}.yaml.log")
42
41
  end
43
42
  end