bleak_house 7.1 → 7.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'dike'
5
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + "/../../lib")
6
+ require 'bleak_house'
7
+
8
+ Dike.logfactory("/tmp")
9
+ if ARGV[0]
10
+ Dike.finger
11
+ exec('cat /tmp/0')
12
+ else
13
+ BleakHouse.snapshot("/tmp/0")
14
+ exec("#{$LOAD_PATH.first}/../bin/bleak /tmp/0")
15
+ end
16
+
@@ -0,0 +1,6 @@
1
+
2
+ require 'test/unit'
3
+ require 'open-uri'
4
+
5
+ HERE = File.expand_path(File.dirname(__FILE__))
6
+ $LOAD_PATH << HERE
@@ -1,33 +1,58 @@
1
1
 
2
- DIR = File.dirname(__FILE__) + "/../../"
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + "/../../lib")
3
3
 
4
+ ENV['NO_EXIT_HANDLER'] = "1"
5
+
6
+ require 'bleak_house'
4
7
  require 'rubygems'
8
+ require 'echoe'
5
9
  require 'test/unit'
6
- require 'yaml'
7
-
10
+
8
11
  class BleakHouseTest < Test::Unit::TestCase
9
- require "#{DIR}lib/bleak_house/c"
10
12
 
11
- SNAPSHOT_FILE = "/tmp/bleak_house"
12
- SNAPS = {:c => SNAPSHOT_FILE + ".c.yaml",
13
- :ruby => SNAPSHOT_FILE + ".rb.yaml"}
13
+ # Match the default hook filename, for convenience
14
+ FILE = "/tmp/bleak.#{Process.pid}.000.dump"
14
15
 
15
16
  def setup
17
+ File.delete FILE rescue nil
16
18
  end
17
19
 
18
- def test_c_snapshot
19
- File.delete SNAPS[:c] rescue nil
20
- ::BleakHouse::CLogger.new.snapshot(SNAPS[:c], "c_test", true)
21
- assert File.exist?(SNAPS[:c])
22
- assert_nothing_raised do
23
- assert YAML.load_file(SNAPS[:c]).is_a?(Array)
24
- end
20
+ def test_snapshot
21
+ BleakHouse.snapshot(FILE)
22
+ assert File.exist?(FILE)
23
+ assert BleakHouse.heaps_used > 0
24
+ assert BleakHouse.heaps_length > 0
25
25
  end
26
-
27
- def test_c_raises
26
+
27
+ def test_snapshot_gc_runs
28
+ BleakHouse.snapshot(FILE, 0)
29
+ assert File.exist?(FILE)
30
+ assert BleakHouse.heaps_used > 0
31
+ assert BleakHouse.heaps_length > 0
32
+ end
33
+
34
+ def test_exception
28
35
  assert_raises(RuntimeError) do
29
- ::BleakHouse::CLogger.new.snapshot("/", "c_test", true)
30
- end
36
+ BleakHouse.snapshot("/")
37
+ end
31
38
  end
32
-
39
+
40
+ def test_analyze
41
+ BleakHouse.snapshot(FILE)
42
+ Dir.chdir(File.dirname(__FILE__) + "/../../bin") do
43
+ output = `./bleak #{FILE}`.split("\n")
44
+ # require 'ruby-debug/debugger'
45
+ assert_match(/top 20 most common/, output[0])
46
+ assert_match(/free heap/, output[3])
47
+ assert_match(/\d+ __null__:__null__:__node__/, output[5])
48
+ end
49
+ end
50
+
51
+ def test_signal
52
+ Echoe.silence do
53
+ system("kill -s SIGUSR2 #{Process.pid}")
54
+ end
55
+ assert File.exist?(FILE)
56
+ end
57
+
33
58
  end
metadata CHANGED
@@ -1,116 +1,112 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.4
3
- specification_version: 1
4
2
  name: bleak_house
5
3
  version: !ruby/object:Gem::Version
6
- version: "7.1"
7
- date: 2007-08-06 00:00:00 -04:00
8
- summary: A Rails plugin for finding memory leaks.
9
- require_paths:
10
- - lib
11
- email: ""
12
- homepage: http://blog.evanweaver.com/pages/code#bleak_house
13
- rubyforge_project: fauna
14
- description: A Rails plugin for finding memory leaks.
15
- autorequire:
16
- default_executable:
17
- bindir: bin
18
- has_rdoc: true
19
- required_ruby_version: !ruby/object:Gem::Version::Requirement
20
- requirements:
21
- - - ">"
22
- - !ruby/object:Gem::Version
23
- version: 0.0.0
24
- version:
4
+ version: "7.2"
25
5
  platform: ruby
26
- signing_key:
27
- cert_chain:
28
- post_install_message: |+
29
-
30
- Thanks for installing BleakHouse.
31
-
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
-
35
- namespace :bleak_house do
36
- desc 'Analyze and chart all data'
37
- task :analyze do
38
- require 'bleak_house/analyze'
39
- BleakHouse::Analyze.build_all("#{RAILS_ROOT}/log/bleak_house_#{RAILS_ENV}.yaml.log")
40
- end
41
- end
42
-
43
-
44
6
  authors:
45
7
  - Evan Weaver
46
- files:
47
- - test/unit/test_bleak_house.rb
48
- - test/misc/direct.rb
49
- - tasks/bleak_house_tasks.rake
50
- - patches/gc.c.patch
51
- - lib/bleak_house.rb
52
- - lib/bleak_house/support_methods.rb
53
- - lib/bleak_house/rake_task_redefine_task.rb
54
- - lib/bleak_house/gruff_hacks.rb
55
- - lib/bleak_house/dispatcher.rb
56
- - lib/bleak_house/c.rb
57
- - lib/bleak_house/bleak_house.rb
58
- - lib/bleak_house/analyze.rb
59
- - lib/bleak_house/action_controller.rb
60
- - install.rb
61
- - init.rb
62
- - Rakefile
63
- - README
64
- - Manifest
65
- - LICENSE_BSD
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIDLjCCAhagAwIBAgIBADANBgkqhkiG9w0BAQUFADA9MQ0wCwYDVQQDDARldmFu
14
+ MRgwFgYKCZImiZPyLGQBGRYIY2xvdWRidXIxEjAQBgoJkiaJk/IsZAEZFgJzdDAe
15
+ Fw0wNzA5MTYxMDMzMDBaFw0wODA5MTUxMDMzMDBaMD0xDTALBgNVBAMMBGV2YW4x
16
+ GDAWBgoJkiaJk/IsZAEZFghjbG91ZGJ1cjESMBAGCgmSJomT8ixkARkWAnN0MIIB
17
+ IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5C0Io89nyApnr+PvbNFge9Vs
18
+ yRWAlGBUEMahpXp28VrrfXZT0rAW7JBo4PlCE3jl4nE4dzE6gAdItSycjTosrw7A
19
+ Ir5+xoyl4Vb35adv56TIQQXvNz+BzlqnkAY5JN0CSBRTQb6mxS3hFyD/h4qgDosj
20
+ R2RFVzHqSxCS8xq4Ny8uzOwOi+Xyu4w67fI5JvnPvMxqrlR1eaIQHmxnf76RzC46
21
+ QO5QhufjAYGGXd960XzbQsQyTDUYJzrvT7AdOfiyZzKQykKt8dEpDn+QPjFTnGnT
22
+ QmgJBX5WJN0lHF2l1sbv3gh4Kn1tZu+kTUqeXY6ShAoDTyvZRiFqQdwh8w2lTQID
23
+ AQABozkwNzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQU+WqJz3xQ
24
+ XSea1hRvvHWcIMgeeC4wDQYJKoZIhvcNAQEFBQADggEBAGLZ75jfOEW8Nsl26CTt
25
+ JFrWxQTcQT/UljeefVE3xYr7lc9oQjbqO3FOyued3qW7TaNEtZfSHoYeUSMYbpw1
26
+ XAwocIPuSRFDGM4B+hgQGVDx8PMGiJKom4qLXjO40UZsR7QyN/u869Vj45LURm6h
27
+ MBcPeqCASI+WNprj9+uZa2kmHiitrFqqfMBNlm5IFbn9XeYSta9AHVvs5QQqV2m5
28
+ hIPfLqCyxsn/YgOGvo6iwyQTWyTswamaAC3HRWZxIS1sfn/Ssqa7E7oQMkv5FAXr
29
+ x5rKePfXINf8XTJczkl9OBEYdE9aNdJsJpXD0asLgGVwBICS5Bjohp6mizJcDC1+
30
+ yZ0=
31
+ -----END CERTIFICATE-----
32
+
33
+ date: 2009-11-18 00:00:00 -08:00
34
+ default_executable:
35
+ dependencies: []
36
+
37
+ description: A library for finding memory leaks.
38
+ email: ""
39
+ executables:
40
+ - bleak
41
+ extensions:
42
+ - ext/extconf.rb
43
+ extra_rdoc_files:
44
+ - CHANGELOG
66
45
  - LICENSE
46
+ - LICENSE_BSD
47
+ - README
48
+ - TODO
49
+ - ext/snapshot.c
50
+ - lib/bleak_house.rb
51
+ - lib/bleak_house/analyzer.rb
52
+ - lib/bleak_house/hook.rb
53
+ files:
67
54
  - CHANGELOG
68
- test_files:
55
+ - LICENSE
56
+ - LICENSE_BSD
57
+ - Manifest
58
+ - README
59
+ - Rakefile
60
+ - TODO
61
+ - bin/bleak
62
+ - ext/build_ruby.rb
63
+ - ext/build_snapshot.rb
64
+ - ext/extconf.rb
65
+ - ext/snapshot.c
66
+ - ext/snapshot.h
67
+ - lib/bleak_house.rb
68
+ - lib/bleak_house/analyzer.rb
69
+ - lib/bleak_house/hook.rb
70
+ - ruby/ruby-1.8.7-p174.tar.bz2
71
+ - ruby/ruby-1.8.7.patch
72
+ - test/benchmark/bench.rb
73
+ - test/test_helper.rb
69
74
  - test/unit/test_bleak_house.rb
70
- rdoc_options: []
71
-
72
- extra_rdoc_files: []
73
-
74
- executables: []
75
-
76
- extensions: []
75
+ - bleak_house.gemspec
76
+ has_rdoc: true
77
+ homepage: http://blog.evanweaver.com/files/doc/fauna/bleak_house/
78
+ licenses: []
77
79
 
80
+ post_install_message:
81
+ rdoc_options:
82
+ - --line-numbers
83
+ - --inline-source
84
+ - --title
85
+ - Bleak_house
86
+ - --main
87
+ - README
88
+ require_paths:
89
+ - lib
90
+ - ext
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: "0"
96
+ version:
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: "1.2"
102
+ version:
78
103
  requirements: []
79
104
 
80
- dependencies:
81
- - !ruby/object:Gem::Dependency
82
- name: gruff
83
- version_requirement:
84
- version_requirements: !ruby/object:Gem::Version::Requirement
85
- requirements:
86
- - - "="
87
- - !ruby/object:Gem::Version
88
- version: 0.2.8
89
- version:
90
- - !ruby/object:Gem::Dependency
91
- name: rmagick
92
- version_requirement:
93
- version_requirements: !ruby/object:Gem::Version::Requirement
94
- requirements:
95
- - - ">"
96
- - !ruby/object:Gem::Version
97
- version: 0.0.0
98
- version:
99
- - !ruby/object:Gem::Dependency
100
- name: activesupport
101
- version_requirement:
102
- version_requirements: !ruby/object:Gem::Version::Requirement
103
- requirements:
104
- - - ">"
105
- - !ruby/object:Gem::Version
106
- version: 0.0.0
107
- version:
108
- - !ruby/object:Gem::Dependency
109
- name: RubyInline
110
- version_requirement:
111
- version_requirements: !ruby/object:Gem::Version::Requirement
112
- requirements:
113
- - - ">"
114
- - !ruby/object:Gem::Version
115
- version: 0.0.0
116
- version:
105
+ rubyforge_project: fauna
106
+ rubygems_version: 1.3.5
107
+ signing_key:
108
+ specification_version: 3
109
+ summary: A library for finding memory leaks.
110
+ test_files:
111
+ - test/test_helper.rb
112
+ - test/unit/test_bleak_house.rb
@@ -0,0 +1,2 @@
1
+ �UcNt@J�-�S�:�νN�wYi�\��.Z�������@��8�A��Lg���
2
+ 8k3&DL�R��7/�G��ڈ�c��x�ZF�(B<��I�U���@:﬊a]1�+(C�g����س2 ,�ˠ1�v���e�Y�XUӚ�V�"��Rb Ȇt1Mzn�+�ol<|���Z���0��Cst�:���+�����J롰�Fs�R��>m-�o�gb���9a��/�{�yo����Pm i��Tv�v[���� �(
data/init.rb DELETED
@@ -1,2 +0,0 @@
1
-
2
- require 'bleak_house'
data/install.rb DELETED
@@ -1,7 +0,0 @@
1
- puts "
2
-
3
- I was such a shy little thing that I seldom dared to open my lips,
4
- and never dared to open my heart, to anybody else.
5
- - Dickens, Bleak House
6
-
7
- "
@@ -1,17 +0,0 @@
1
-
2
- # Override ActionController::Base.process and process_with_exception to make sure the request tag for the snapshot gets set as a side-effect of request processing.
3
- class ActionController::Base
4
- class << self
5
- def process_with_bleak_house(request, *args)
6
- BleakHouse.set_request_name request
7
- process_without_bleak_house(request, *args)
8
- end
9
- alias_method_chain :process, :bleak_house
10
-
11
- def process_with_exception_with_bleak_house(request, *args)
12
- BleakHouse.set_request_name request, "/error"
13
- process_with_exception_without_bleak_house(request, *args)
14
- end
15
- alias_method_chain :process_with_exception, :bleak_house
16
- end
17
- end
@@ -1,196 +0,0 @@
1
-
2
- require 'rubygems'
3
- require 'fileutils'
4
- require 'yaml'
5
- require 'active_support'
6
-
7
- gem 'gruff', '= 0.2.8'
8
- require 'gruff'
9
-
10
- # require, but make rdoc not whine
11
- load "#{File.dirname(__FILE__)}/gruff_hacks.rb"
12
- load "#{File.dirname(__FILE__)}/support_methods.rb"
13
-
14
- Gruff::Base.send(:remove_const, "LEFT_MARGIN") # silence a warning
15
- Gruff::Base::LEFT_MARGIN = 200
16
- Gruff::Base::NEGATIVE_TOP_MARGIN = 30
17
- Gruff::Base::MAX_LEGENDS = 28
18
-
19
- class BleakHouse
20
- # Draws the BleakHouse graphs.
21
- class Analyze
22
-
23
- SMOOTHNESS = ENV['SMOOTHNESS'].to_i.zero? ? 1 : ENV['SMOOTHNESS'].to_i
24
- MEM_KEY = "memory usage"
25
- HEAP_KEY = "heap usage"
26
- CORE_KEY = "core rails"
27
-
28
- # Sets up a single graph.
29
- def initialize(data, increments, name)
30
- @data = data
31
- @increments = increments
32
- @name = name
33
- end
34
-
35
- def d #:nodoc:
36
- self.class.d
37
- end
38
-
39
- # Draw <tt>self</tt>. Use some special attributes added to Gruff. Requires the overrides in <tt>gruff_hacks.rb</tt>.
40
- def draw #:nodoc:
41
- g = Gruff::Line.new("1024x768")
42
- g.title = @name
43
- g.x_axis_label = "time"
44
- g.legend_font_size = g.legend_box_size = 14
45
- g.title_font_size = 24
46
- g.marker_font_size = 14
47
-
48
- # mangle some key names.
49
- # XXX unreadable
50
- @data.map do |key, values|
51
- ["#{(key.to_s.empty? ? '[Unknown]' : key).gsub(/.*::/, '')} (#{ if
52
- [MEM_KEY, HEAP_KEY].include?(key)
53
- 'relative'
54
- else
55
- values.to_i.max
56
- end })", values] # hax
57
- end.sort_by do |key, values|
58
- 0 - key[/.*?([\d]+)\)$/, 1].to_i
59
- end.each do |key, values|
60
- g.data(key, values.to_i)
61
- end
62
-
63
- labels = {}
64
- mod = (@increments.size / 4.0).ceil
65
- @increments.each_with_index do |increment, index|
66
- labels[index] = increment if (index % mod).zero?
67
- end
68
-
69
- g.labels = labels
70
-
71
- g.minimum_value = 0
72
- # g.maximum_value = @maximum
73
-
74
- g.write(@name.to_filename + ".png")
75
- end
76
-
77
- # Takes subkeys that match the <tt>selector</tt> regex and adds each subkey's count to the key named by the first group match in the <tt>namer</tt> regex for that subkey.
78
- def self.aggregate(data, selector = //, namer = //) #:nodoc:
79
- aggregate_data = {}
80
- increments = []
81
- data.each_with_index do |frameset, index|
82
- increments << frameset.time
83
- frameset.data.keys.select do |key|
84
- # aggregate common keys based on the selection regexs
85
- key =~ selector
86
- end.each do |key|
87
- aggregate_data[key.to_s[namer, 1]] ||= []
88
- aggregate_data[key.to_s[namer, 1]][index] += frameset.data[key].to_i
89
- end
90
- end
91
- aggregate_data.each do |key, value|
92
- # extend the length of every value set to the end of the run
93
- aggregate_data[key][increments.size - 1] ||= nil
94
- end
95
- [aggregate_data, increments]
96
- end
97
-
98
- # Generates a chart for each tag (by subtag) and subtag (by object type). Output is written to <tt>bleak_house/</tt> in the same folder as the passed <tt>logfile</tt> attribute.
99
- def self.build_all(logfile)
100
- unless File.exists? logfile
101
- puts "No data file found: #{logfile}"
102
- exit
103
- end
104
- puts "parsing data"
105
- data = YAML.load_file(logfile)
106
-
107
- rootdir = File.dirname(logfile) + "/bleak_house/"
108
- FileUtils.rm_r(rootdir) rescue nil
109
- Dir.mkdir(rootdir)
110
- Dir.chdir(rootdir) do
111
-
112
- labels = []
113
-
114
- # autodetect need for Rails snapshot conflation
115
- if data.first.last.keys.first =~ /^#{CORE_KEY}::::/
116
- # Rails snapshots double-count objects that start in the core and persist through the action (which is most core objects), so we need to the subtract core counts from action counts
117
- data = data[0..(-1 - data.size % 2)]
118
- data = data.in_groups_of(2).map do |frames|
119
- core, action = frames.first, frames.last
120
- action.data.each do |key, value|
121
- action.data[key] = value - core.data[key[/::::(.*)/,1]].to_i
122
- end
123
- [action.time, core.data.merge(action.data)]
124
- end
125
- puts " conflated core rails snapshots with their actions"
126
- labels = ["controller", "action"]
127
- else
128
- puts " assuming custom snapshotting"
129
- labels = ["tag", "subtag"]
130
- end
131
-
132
- # smooth frames (just an average)
133
- data = data[0..(-1 - data.size % SMOOTHNESS)]
134
- data = data.in_groups_of(SMOOTHNESS).map do |frames|
135
- timestamp = frames.map(&:time).sum / SMOOTHNESS
136
- values = frames.map(&:data).inject(Hash.new(0)) do |total, this_frame|
137
- this_frame.each do |key, value|
138
- total[key] += value / SMOOTHNESS.to_f
139
- end
140
- end
141
- [Time.at(timestamp).strftime("%H:%M:%S"), values]
142
- end
143
- puts " #{data.size} frames after smoothing"
144
-
145
- # scale memory/heap frames
146
- controller_data, increments = aggregate(data, //, /^(.*?)($|\/|::::)/)
147
- controller_data_without_specials = controller_data.dup
148
- controller_data_without_specials.delete(MEM_KEY)
149
- controller_data_without_specials.delete(HEAP_KEY)
150
- [HEAP_KEY, MEM_KEY].each do |key|
151
- scale_factor = controller_data_without_specials.values.flatten.to_i.max / controller_data[key].max.to_f * 0.8 rescue 1
152
- controller_data[key] = controller_data[key].map{|x| (x * scale_factor).to_i }
153
- end
154
-
155
- # generate initial controller graph
156
- puts(title = "objects by #{labels[0]}")
157
- Analyze.new(controller_data, increments, title).draw
158
-
159
- # in each controller, by action
160
- controller_data.keys.each do |controller|
161
- # next unless controller == HEAP_KEY
162
- @mem = [MEM_KEY, HEAP_KEY].include? controller
163
- @core = [CORE_KEY].include? controller
164
- Dir.descend(controller) do
165
- action_data, increments = aggregate(data, /^#{controller}($|\/|::::)/, /\/(.*?)($|\/|::::)/)
166
- unless @core
167
- puts(" " + (title = case controller
168
- when MEM_KEY then "#{controller} in kilobytes"
169
- when HEAP_KEY then "#{controller} in slots"
170
- else "objects by #{labels[1]} in /#{controller}/"
171
- end))
172
- Analyze.new(action_data, increments, title).draw
173
- end
174
-
175
- # in each action, by object class
176
- action_data.keys.each do |action|
177
- action = "unknown" if action.to_s == ""
178
- Dir.descend(@core ? "." : action) do
179
- puts((@core ? " " : " ") + (title = "objects by class in #{@core ? CORE_KEY : "/#{controller}/#{action}"}"))
180
- class_data, increments = aggregate(data, /^#{controller}#{"\/#{action}" unless action == "unknown"}($|\/|::::)/,
181
- /::::(.*)/)
182
- Analyze.new(class_data, increments, title).draw
183
- end
184
- end unless @mem
185
-
186
- end
187
- end
188
- end
189
- end
190
-
191
- def self.d #:nodoc:
192
- require 'ruby-debug'; Debugger.start; debugger
193
- end
194
-
195
- end
196
- end