bleak_house 6 → 7

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 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