bleak_house 3 → 3.0.1
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 +26 -4
- data/LICENSE_BSD +10 -0
- data/LICENSE_RUBY +53 -0
- data/Manifest +30 -18
- data/README +66 -13
- data/Rakefile +63 -56
- data/TODO +2 -0
- data/bin/bleak +10 -0
- data/ext/bleak_house/logger/extconf.rb +4 -0
- data/ext/bleak_house/logger/snapshot.c +153 -0
- data/ext/bleak_house/logger/snapshot.h +99 -0
- data/init.rb +2 -1
- data/install.rb +2 -1
- data/lib/bleak_house/analyzer/analyzer.rb +143 -0
- data/lib/bleak_house/analyzer.rb +5 -0
- data/lib/bleak_house/logger/mem_usage.rb +13 -0
- data/lib/bleak_house/logger.rb +3 -0
- data/lib/bleak_house/{action_controller.rb → rails/action_controller.rb} +3 -2
- data/lib/bleak_house/rails/bleak_house.rb +58 -0
- data/lib/bleak_house/rails/dispatcher.rb +19 -0
- data/lib/bleak_house/rails.rb +6 -0
- data/lib/bleak_house/{support_methods.rb → support/core_extensions.rb} +24 -1
- data/lib/bleak_house/{rake_task_redefine_task.rb → support/rake.rb} +0 -0
- data/lib/bleak_house.rb +4 -10
- data/lib/vendor/lightcsv.rb +168 -0
- data/patches/gc.c.patch +27 -0
- data/patches/parse.y.patch +16 -0
- data/test/misc/direct.rb +13 -0
- data/test/unit/test_bleak_house.rb +34 -0
- data.tar.gz.sig +3 -0
- metadata +77 -50
- metadata.gz.sig +0 -0
- data/lib/bleak_house/analyze.rb +0 -139
- data/lib/bleak_house/bleak_house.rb +0 -33
- data/lib/bleak_house/dispatcher.rb +0 -23
- data/lib/bleak_house/gruff_hacks.rb +0 -56
- data/lib/bleak_house/mem_logger.rb +0 -54
- data/tasks/bleak_house_tasks.rake +0 -13
@@ -0,0 +1,143 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'yaml'
|
5
|
+
require 'pp'
|
6
|
+
require 'ruby-debug'
|
7
|
+
|
8
|
+
module BleakHouse
|
9
|
+
|
10
|
+
class Analyzer
|
11
|
+
|
12
|
+
MAGIC_KEYS = {
|
13
|
+
-1 => 'timestamp',
|
14
|
+
-2 => 'mem usage/swap',
|
15
|
+
-3 => 'mem usage/real',
|
16
|
+
-4 => 'tag',
|
17
|
+
-5 => 'heap/filled',
|
18
|
+
-6 => 'heap/free'
|
19
|
+
}
|
20
|
+
|
21
|
+
CLASS_KEYS = eval('[nil, ' + # skip 0
|
22
|
+
open(
|
23
|
+
File.dirname(__FILE__) + '/../../../ext/bleak_house/logger/snapshot.h'
|
24
|
+
).read[/\{(.*?)\}/m, 1] + ']')
|
25
|
+
|
26
|
+
# Parses and correlates a BleakHouse::Logger output file.
|
27
|
+
def self.run(logfile)
|
28
|
+
unless File.exists? logfile
|
29
|
+
puts "No data file found: #{logfile}"
|
30
|
+
exit
|
31
|
+
end
|
32
|
+
|
33
|
+
frames = []
|
34
|
+
last_population = []
|
35
|
+
frame = nil
|
36
|
+
ix = nil
|
37
|
+
|
38
|
+
puts "Examining objects"
|
39
|
+
|
40
|
+
LightCsv.foreach(logfile) do |row|
|
41
|
+
|
42
|
+
# Stupid is fast
|
43
|
+
row[0] = row[0].to_i if row[0].to_i != 0
|
44
|
+
row[1] = row[1].to_i if row[1].to_i != 0
|
45
|
+
|
46
|
+
if row[0].to_i < 0
|
47
|
+
# Get frame meta-information
|
48
|
+
if MAGIC_KEYS[row[0]] == 'timestamp'
|
49
|
+
|
50
|
+
# The frame has ended; process the last one
|
51
|
+
if frame
|
52
|
+
population = frame['objects'].keys
|
53
|
+
births = population - last_population
|
54
|
+
deaths = last_population - population
|
55
|
+
last_population = population
|
56
|
+
|
57
|
+
# assign births
|
58
|
+
frame['births'] = frame['objects'].slice(births)
|
59
|
+
|
60
|
+
if final = frames[-2]
|
61
|
+
final['deaths'] = final['objects'].slice(deaths)
|
62
|
+
bsize = final['births'].size
|
63
|
+
dsize = final['deaths'].size
|
64
|
+
final['velocity'] = bsize * 100 / dsize / 100.0
|
65
|
+
puts " Frame #{frames.size - 1} (#{final['meta']['tag]}) finalized: #{bsize} births, #{dsize} deaths, velocity #{final['velocity']}, population #{final['objects'].size}"
|
66
|
+
final.delete 'objects'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Set up a new frame
|
71
|
+
frame = {}
|
72
|
+
frames << frame
|
73
|
+
frame['objects'] ||= {}
|
74
|
+
frame['meta'] ||= {}
|
75
|
+
|
76
|
+
#puts " Frame #{frames.size} opened"
|
77
|
+
end
|
78
|
+
|
79
|
+
frame['meta'][MAGIC_KEYS[row[0]]] = row[1]
|
80
|
+
else
|
81
|
+
# Assign live objects
|
82
|
+
frame['objects'][row[1]] = row[0]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# See what objects are still laying around
|
87
|
+
population = frames.last['objects'].reject do |key, value|
|
88
|
+
frames.first['births'][key] == value
|
89
|
+
end
|
90
|
+
|
91
|
+
# Remove bogus frames
|
92
|
+
frames = frames[1..-3]
|
93
|
+
|
94
|
+
total_births = frames.inject(0) do |births, frame|
|
95
|
+
births + frame['births'].size
|
96
|
+
end
|
97
|
+
total_deaths = frames.inject(0) do |deaths, frame|
|
98
|
+
deaths + frame['deaths'].size
|
99
|
+
end
|
100
|
+
|
101
|
+
puts "#{total_births} total meaningful births, #{total_deaths} total meaningful deaths.\n\n"
|
102
|
+
|
103
|
+
leakers = {}
|
104
|
+
|
105
|
+
# Find the sources of the leftover objects in the final population
|
106
|
+
population.each do |id, klass|
|
107
|
+
leaker = frames.detect do |frame|
|
108
|
+
frame['births'][id] == klass
|
109
|
+
end
|
110
|
+
if leaker
|
111
|
+
tag = leaker['meta']['tag']
|
112
|
+
klass = CLASS_KEYS[klass] if klass.is_a? Fixnum
|
113
|
+
leakers[tag] ||= Hash.new(0)
|
114
|
+
leakers[tag][klass] += 1
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Sort
|
119
|
+
leakers = leakers.map do |tag, value|
|
120
|
+
[tag, value.sort_by do |klass, count|
|
121
|
+
-count
|
122
|
+
end]
|
123
|
+
end.sort_by do |tag, value|
|
124
|
+
Hash[*value.flatten].values.inject(0) {|i, v| i - v}
|
125
|
+
end
|
126
|
+
|
127
|
+
puts "Here are your leaks:"
|
128
|
+
leakers.each do |tag, value|
|
129
|
+
puts " #{tag} leaked per request:"
|
130
|
+
requests = frames.select do |frame|
|
131
|
+
frame['meta']['tag'] == tag
|
132
|
+
end.size
|
133
|
+
value.each do |klass, count|
|
134
|
+
count = count/requests
|
135
|
+
puts " #{count} #{klass}" if count > 0
|
136
|
+
end
|
137
|
+
end
|
138
|
+
puts "\nBye"
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
|
2
|
+
module BleakHouse
|
3
|
+
|
4
|
+
class Logger
|
5
|
+
|
6
|
+
# Returns an array of the running process's real and virtual memory usage, in kilobytes.
|
7
|
+
def mem_usage
|
8
|
+
a = `ps -o vsz,rss -p #{Process.pid}`.split(/\s+/)[-2..-1].map{|el| el.to_i}
|
9
|
+
[a.first - a.last, a.last]
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -1,14 +1,15 @@
|
|
1
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.
|
2
3
|
class ActionController::Base
|
3
4
|
class << self
|
4
5
|
def process_with_bleak_house(request, *args)
|
5
|
-
BleakHouse.set_request_name request
|
6
|
+
BleakHouse::Rails.set_request_name request
|
6
7
|
process_without_bleak_house(request, *args)
|
7
8
|
end
|
8
9
|
alias_method_chain :process, :bleak_house
|
9
10
|
|
10
11
|
def process_with_exception_with_bleak_house(request, *args)
|
11
|
-
BleakHouse.set_request_name request, "/error"
|
12
|
+
BleakHouse::Rails.set_request_name request, "/error"
|
12
13
|
process_with_exception_without_bleak_house(request, *args)
|
13
14
|
end
|
14
15
|
alias_method_chain :process_with_exception, :bleak_house
|
@@ -0,0 +1,58 @@
|
|
1
|
+
|
2
|
+
module BleakHouse
|
3
|
+
module Rails
|
4
|
+
class << self
|
5
|
+
|
6
|
+
def last_request_name
|
7
|
+
@@last_request_name
|
8
|
+
end
|
9
|
+
|
10
|
+
def last_request_name=(obj)
|
11
|
+
@@last_request_name = obj
|
12
|
+
end
|
13
|
+
|
14
|
+
# Avoid making four more strings on each request.
|
15
|
+
CONTROLLER_KEY = 'controller'
|
16
|
+
ACTION_KEY = 'action'
|
17
|
+
GSUB_SEARCH = '/'
|
18
|
+
GSUB_REPLACEMENT = '__'
|
19
|
+
|
20
|
+
# Sets the request name on the BleakHouse object to match this Rails request. Called from <tt>ActionController::Base.process</tt>. Assign to <tt>last_request_name</tt> yourself if you are not using BleakHouse within Rails.
|
21
|
+
def set_request_name(request, other = nil)
|
22
|
+
self.last_request_name = "#{
|
23
|
+
request.parameters[CONTROLLER_KEY].gsub(GSUB_SEARCH, GSUB_REPLACEMENT) # mangle namespaced controller names
|
24
|
+
}/#{
|
25
|
+
request.parameters[ACTION_KEY]
|
26
|
+
}/#{
|
27
|
+
request.request_method
|
28
|
+
}#{
|
29
|
+
other
|
30
|
+
}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def debug(s) #:nodoc:
|
34
|
+
s = "** bleak_house: #{s}"
|
35
|
+
RAILS_DEFAULT_LOGGER.debug s if RAILS_DEFAULT_LOGGER
|
36
|
+
end
|
37
|
+
|
38
|
+
def warn(s) #:nodoc:
|
39
|
+
s = "** bleak_house: #{s}"
|
40
|
+
if RAILS_DEFAULT_LOGGER
|
41
|
+
RAILS_DEFAULT_LOGGER.warn s
|
42
|
+
else
|
43
|
+
$stderr.puts s
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
LOGFILE = "#{RAILS_ROOT}/log/bleak_house_#{RAILS_ENV}.dump"
|
49
|
+
if File.exists?(LOGFILE)
|
50
|
+
File.rename(LOGFILE, "#{LOGFILE}.old")
|
51
|
+
warn "renamed old logfile"
|
52
|
+
end
|
53
|
+
|
54
|
+
WITH_SPECIALS = false
|
55
|
+
|
56
|
+
MEMLOGGER = Logger.new
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
# Override Dispatcher#prepare and Dispatcher#reset_after_dispatch so that each request makes before-and-after usage snapshots.
|
3
|
+
class Dispatcher
|
4
|
+
class << self
|
5
|
+
|
6
|
+
def prepare_application_with_bleak_house
|
7
|
+
prepare_application_without_bleak_house
|
8
|
+
BleakHouse::Rails::MEMLOGGER.snapshot(BleakHouse::Rails::LOGFILE, 'core rails', BleakHouse::Rails::WITH_SPECIALS)
|
9
|
+
end
|
10
|
+
alias_method_chain :prepare_application, :bleak_house
|
11
|
+
|
12
|
+
def reset_after_dispatch_with_bleak_house
|
13
|
+
BleakHouse::Rails::MEMLOGGER.snapshot(BleakHouse::Rails::LOGFILE, BleakHouse::Rails.last_request_name || 'unknown', BleakHouse::Rails::WITH_SPECIALS)
|
14
|
+
reset_after_dispatch_without_bleak_house
|
15
|
+
end
|
16
|
+
alias_method_chain :reset_after_dispatch, :bleak_house
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -1,4 +1,6 @@
|
|
1
1
|
|
2
|
+
require 'set'
|
3
|
+
|
2
4
|
class Array
|
3
5
|
alias :time :first
|
4
6
|
alias :data :last
|
@@ -13,10 +15,28 @@ class Array
|
|
13
15
|
|
14
16
|
end
|
15
17
|
|
18
|
+
class Hash
|
19
|
+
|
20
|
+
# Similar to the ActiveSupport methods in Rails
|
21
|
+
def slice(keys)
|
22
|
+
keys = Set.new(keys)
|
23
|
+
reject do |key,|
|
24
|
+
!keys.include?(key)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def unslice(keys)
|
29
|
+
keys = Set.new(keys)
|
30
|
+
reject do |key,|
|
31
|
+
keys.include?(key)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
16
36
|
class Dir
|
17
37
|
def self.descend path, &block
|
18
38
|
path = path.split("/") unless path.is_a? Array
|
19
|
-
top = path.shift
|
39
|
+
top = (path.shift or ".")
|
20
40
|
Dir.mkdir(top) unless File.exists? top
|
21
41
|
Dir.chdir(top) do
|
22
42
|
if path.any?
|
@@ -44,4 +64,7 @@ class Symbol
|
|
44
64
|
def =~ regex
|
45
65
|
self.to_s =~ regex
|
46
66
|
end
|
67
|
+
def [](*args)
|
68
|
+
self.to_s[*args]
|
69
|
+
end
|
47
70
|
end
|
File without changes
|
data/lib/bleak_house.rb
CHANGED
@@ -1,13 +1,7 @@
|
|
1
1
|
|
2
|
-
|
2
|
+
require 'bleak_house/logger'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
require 'bleak_house/mem_logger'
|
8
|
-
require 'bleak_house/dispatcher'
|
9
|
-
require 'bleak_house/action_controller'
|
10
|
-
|
11
|
-
BleakHouse.warn "enabled (log/#{RAILS_ENV}_bleak_house.log) (#{BleakHouse.log_interval} requests per frame)"
|
12
|
-
|
4
|
+
if ENV['RAILS_ENV'] and ENV['BLEAK_HOUSE']
|
5
|
+
require 'bleak_house/rails'
|
6
|
+
BleakHouse::Rails.warn "enabled (log/bleak_house_#{RAILS_ENV}.dump)"
|
13
7
|
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
# = LightCsv
|
2
|
+
# CSV parser
|
3
|
+
#
|
4
|
+
# $Id: lightcsv.rb 76 2007-04-15 14:34:23Z tommy $
|
5
|
+
# Copyright:: 2007 (C) TOMITA Masahiro <tommy@tmtm.org>
|
6
|
+
# License:: Ruby's
|
7
|
+
# Homepage:: http://tmtm.org/ja/ruby/lightcsv
|
8
|
+
|
9
|
+
require "strscan"
|
10
|
+
|
11
|
+
# == CSV のパース
|
12
|
+
# 各レコードはカラムを要素とする配列である。
|
13
|
+
# レコードの区切りは LF,CR,CRLF のいずれか。
|
14
|
+
#
|
15
|
+
# 以下が csv.rb と異なる。
|
16
|
+
# * 空行は [nil] ではなく [] になる。
|
17
|
+
# * 「"」で括られていない空カラムは nil ではなく "" になる。
|
18
|
+
#
|
19
|
+
# == 例
|
20
|
+
# * CSVファイルのレコード毎にブロックを繰り返す。
|
21
|
+
# LightCsv.foreach(filename){|row| ...}
|
22
|
+
# 次と同じ。
|
23
|
+
# LightCsv.open(filename){|csv| csv.each{|row| ...}}
|
24
|
+
#
|
25
|
+
# * CSVファイルの全レコードを返す。
|
26
|
+
# LightCsv.readlines(filename) # => [[col1,col2,...],...]
|
27
|
+
# 次と同じ。
|
28
|
+
# LightCsv.open(filename){|csv| csv.map}
|
29
|
+
#
|
30
|
+
# * CSV文字列のレコード毎にブロックを繰り返す。
|
31
|
+
# LightCsv.parse("a1,a2,..."){|row| ...}
|
32
|
+
# 次と同じ。
|
33
|
+
# LightCsv.new("a1,a2,...").each{|row| ...}
|
34
|
+
#
|
35
|
+
# * CSV文字列の全レコードを返す。
|
36
|
+
# LightCsv.parse("a1,a2,...") # => [[a1,a2,...],...]
|
37
|
+
# 次と同じ。
|
38
|
+
# LightCsv.new("a1,a2,...").map
|
39
|
+
#
|
40
|
+
class LightCsv
|
41
|
+
include Enumerable
|
42
|
+
|
43
|
+
# == パースできない形式の場合に発生する例外
|
44
|
+
# InvalidFormat#message は処理できなかった位置から 10バイト文の文字列を返す。
|
45
|
+
class InvalidFormat < RuntimeError; end
|
46
|
+
|
47
|
+
# ファイルの各レコード毎にブロックを繰り返す。
|
48
|
+
# ブロック引数はレコードを表す配列。
|
49
|
+
def self.foreach(filename, &block)
|
50
|
+
self.open(filename) do |f|
|
51
|
+
f.each(&block)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# ファイルの全レコードをレコードの配列で返す。
|
56
|
+
def self.readlines(filename)
|
57
|
+
self.open(filename) do |f|
|
58
|
+
return f.map
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# CSV文字列の全レコードをレコードの配列で返す。
|
63
|
+
# ブロックが与えられた場合は、レコード毎にブロックを繰り返す。
|
64
|
+
# ブロック引数はレコードを表す配列。
|
65
|
+
def self.parse(string, &block)
|
66
|
+
unless block
|
67
|
+
return self.new(string).map
|
68
|
+
end
|
69
|
+
self.new(string).each do |row|
|
70
|
+
block.call row
|
71
|
+
end
|
72
|
+
return nil
|
73
|
+
end
|
74
|
+
|
75
|
+
# ファイルをオープンして LightCsv オブジェクトを返す。
|
76
|
+
# ブロックを与えた場合は LightCsv オブジェクトを引数としてブロックを実行する。
|
77
|
+
def self.open(filename, &block)
|
78
|
+
f = File.open(filename)
|
79
|
+
csv = self.new(f)
|
80
|
+
if block
|
81
|
+
begin
|
82
|
+
return block.call(csv)
|
83
|
+
ensure
|
84
|
+
csv.close
|
85
|
+
end
|
86
|
+
else
|
87
|
+
return csv
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# LightCsv オブジェクトを生成する。
|
92
|
+
# _src_ は String か IO。
|
93
|
+
def initialize(src)
|
94
|
+
if src.kind_of? String
|
95
|
+
@file = nil
|
96
|
+
@ss = StringScanner.new(src)
|
97
|
+
else
|
98
|
+
@file = src
|
99
|
+
@ss = StringScanner.new("")
|
100
|
+
end
|
101
|
+
@buf = ""
|
102
|
+
@bufsize = 64*1024
|
103
|
+
end
|
104
|
+
attr_accessor :bufsize
|
105
|
+
|
106
|
+
# LightCsv オブジェクトに関連したファイルをクローズする。
|
107
|
+
def close()
|
108
|
+
@file.close if @file
|
109
|
+
end
|
110
|
+
|
111
|
+
# 1レコードを返す。データの最後の場合は nil を返す。
|
112
|
+
# 空行の場合は空配列([])を返す。
|
113
|
+
# 空カラムは「"」で括られているか否かにかかわらず空文字列("")になる。
|
114
|
+
def shift()
|
115
|
+
return nil if @ss.eos? and ! read_next_data
|
116
|
+
cols = []
|
117
|
+
while true
|
118
|
+
if @ss.eos? and ! read_next_data
|
119
|
+
cols << ""
|
120
|
+
break
|
121
|
+
end
|
122
|
+
if @ss.scan(/\"/n)
|
123
|
+
until @ss.scan(/(?:\"\"|[^\"])*\"/n)
|
124
|
+
read_next_data or raise InvalidFormat, @ss.rest[0,10]
|
125
|
+
end
|
126
|
+
cols << @ss.matched.chop.gsub(/\"\"/n, '"')
|
127
|
+
else
|
128
|
+
col = @ss.scan(/[^\",\r\n]*/n)
|
129
|
+
while @ss.eos? and read_next_data
|
130
|
+
col << @ss.scan(/[^\",\r\n]*/n)
|
131
|
+
end
|
132
|
+
cols << col
|
133
|
+
end
|
134
|
+
unless @ss.scan(/,/n)
|
135
|
+
break if @ss.scan(/\r\n/n)
|
136
|
+
unless @ss.rest_size < 2 and read_next_data and @ss.scan(/,/n)
|
137
|
+
break if @ss.scan(/\r\n|\n|\r|\z/n)
|
138
|
+
read_next_data
|
139
|
+
raise InvalidFormat, @ss.rest[0,10]
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
cols.clear if cols.size == 1 and cols.first.empty?
|
144
|
+
cols
|
145
|
+
end
|
146
|
+
|
147
|
+
# 各レコード毎にブロックを繰り返す。
|
148
|
+
def each()
|
149
|
+
while row = shift
|
150
|
+
yield row
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# 現在位置以降のレコードの配列を返す。
|
155
|
+
def readlines()
|
156
|
+
return map
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
160
|
+
|
161
|
+
def read_next_data()
|
162
|
+
if @file and @file.read(@bufsize, @buf)
|
163
|
+
@ss.string = @ss.rest + @buf
|
164
|
+
else
|
165
|
+
nil
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
data/patches/gc.c.patch
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
*** gc.old 2007-09-25 00:27:27.000000000 -0400
|
2
|
+
--- gc.c 2007-09-25 00:27:28.000000000 -0400
|
3
|
+
***************
|
4
|
+
*** 309,314 ****
|
5
|
+
--- 309,330 ----
|
6
|
+
static int heaps_length = 0;
|
7
|
+
static int heaps_used = 0;
|
8
|
+
|
9
|
+
+ struct heaps_slot *
|
10
|
+
+ rb_gc_heap_slots()
|
11
|
+
+ {
|
12
|
+
+ return heaps;
|
13
|
+
+ }
|
14
|
+
+
|
15
|
+
+ int
|
16
|
+
+ rb_gc_heaps_used() {
|
17
|
+
+ return heaps_used;
|
18
|
+
+ }
|
19
|
+
+
|
20
|
+
+ int
|
21
|
+
+ rb_gc_heaps_length() {
|
22
|
+
+ return heaps_length;
|
23
|
+
+ }
|
24
|
+
+
|
25
|
+
#define HEAP_MIN_SLOTS 10000
|
26
|
+
static int heap_slots = HEAP_MIN_SLOTS;
|
27
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
*** parse.old 2007-09-25 00:21:43.000000000 -0400
|
2
|
+
--- parse.y 2007-09-25 00:23:02.000000000 -0400
|
3
|
+
***************
|
4
|
+
*** 6166,6171 ****
|
5
|
+
--- 6166,6176 ----
|
6
|
+
* :wait2, :$>]
|
7
|
+
*/
|
8
|
+
|
9
|
+
+ struct st_table *
|
10
|
+
+ rb_parse_sym_tbl() {
|
11
|
+
+ return sym_tbl;
|
12
|
+
+ }
|
13
|
+
+
|
14
|
+
VALUE
|
15
|
+
rb_sym_all_symbols()
|
16
|
+
{
|
data/test/misc/direct.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby-bleak-house
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bleak_house/c'
|
5
|
+
$memlogger = BleakHouse::Logger.new
|
6
|
+
File.delete($logfile = "/tmp/log") rescue nil
|
7
|
+
|
8
|
+
puts 0
|
9
|
+
$memlogger.snapshot($logfile, "file", true)
|
10
|
+
puts 1
|
11
|
+
$memlogger.snapshot($logfile, "file/one", true)
|
12
|
+
puts 2
|
13
|
+
$memlogger.snapshot($logfile, "file/two", true)
|
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
DIR = File.dirname(__FILE__) + "/../../"
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'test/unit'
|
6
|
+
require 'yaml'
|
7
|
+
require 'ruby-debug'
|
8
|
+
Debugger.start
|
9
|
+
|
10
|
+
class BleakHouseTest < Test::Unit::TestCase
|
11
|
+
require "#{DIR}lib/bleak_house/logger"
|
12
|
+
|
13
|
+
SNAPSHOT_FILE = "/tmp/bleak_house"
|
14
|
+
SNAPS = {:c => SNAPSHOT_FILE + ".c.yaml",
|
15
|
+
:ruby => SNAPSHOT_FILE + ".rb.yaml"}
|
16
|
+
|
17
|
+
def setup
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_c_snapshot
|
21
|
+
File.delete SNAPS[:c] rescue nil
|
22
|
+
symbol_count = Symbol.all_symbols.size
|
23
|
+
::BleakHouse::Logger.new.snapshot(SNAPS[:c], "c_test", false)
|
24
|
+
assert_equal symbol_count, Symbol.all_symbols.size
|
25
|
+
assert File.exist?(SNAPS[:c])
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_c_raises
|
29
|
+
assert_raises(RuntimeError) do
|
30
|
+
::BleakHouse::Logger.new.snapshot("/", "c_test", false)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data.tar.gz.sig
ADDED