bleak_house 7.1 → 7.2

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.
@@ -1,47 +0,0 @@
1
-
2
- class BleakHouse
3
- cattr_accessor :last_request_name
4
-
5
- # Avoid making four more strings on each request.
6
- CONTROLLER_KEY = 'controller'
7
- ACTION_KEY = 'action'
8
- GSUB_SEARCH = '/'
9
- GSUB_REPLACEMENT = '__'
10
-
11
- # 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.
12
- def self.set_request_name request, other = nil
13
- self.last_request_name = "#{
14
- request.parameters[CONTROLLER_KEY].gsub(GSUB_SEARCH, GSUB_REPLACEMENT) # mangle namespaced controller names
15
- }/#{
16
- request.parameters[ACTION_KEY]
17
- }/#{
18
- request.request_method
19
- }#{
20
- other
21
- }"
22
- end
23
-
24
- def self.debug s #:nodoc:
25
- s = "** #{name.underscore}: #{s}"
26
- RAILS_DEFAULT_LOGGER.debug s if RAILS_DEFAULT_LOGGER
27
- end
28
-
29
- def self.warn s #:nodoc:
30
- s = "** #{name.underscore}: #{s}"
31
- if RAILS_DEFAULT_LOGGER
32
- RAILS_DEFAULT_LOGGER.warn s
33
- else
34
- $stderr.puts s
35
- end
36
- end
37
-
38
- LOGFILE = "#{RAILS_ROOT}/log/bleak_house_#{RAILS_ENV}.yaml.log"
39
- if File.exists?(LOGFILE)
40
- File.rename(LOGFILE, "#{LOGFILE}.old")
41
- warn "renamed old logfile"
42
- end
43
-
44
- WITH_SPECIALS = false
45
-
46
- MEMLOGGER = CLogger.new
47
- end
@@ -1,230 +0,0 @@
1
-
2
- require 'rubygems'
3
- require 'inline'
4
-
5
- class BleakHouse
6
-
7
- =begin rdoc
8
- This class performs the actual object logging of BleakHouse. To use it directly, you need to make calls to BleakHouse::CLogger#snapshot.
9
-
10
- == Example
11
-
12
- At the start of your app, put:
13
- require 'rubygems'
14
- require 'bleak_house/c'
15
- $memlogger = BleakHouse::CLogger.new
16
- File.delete($logfile = "/path/to/logfile") rescue nil
17
-
18
- (This assumes you are using the gem version.)
19
-
20
- Now, at the points of interest, put:
21
- $memlogger.snapshot($logfile, "tag/subtag", false)
22
-
23
- Run your app. Once you are done, analyze your data:
24
- ruby -r rubygems -e 'require "bleak_house/analyze"; BleakHouse::Analyze.build_all("/path/to/logfile")'
25
-
26
- You will get a <tt>bleak_house/</tt> folder in the same folder as your logfile.
27
-
28
- =end
29
-
30
- class CLogger
31
-
32
- MAX_UNIQ_TAGS = 1536 # per frame
33
- MAX_TAG_LENGTH = 192 # tag plus fully namespaced classname
34
-
35
- # Returns an array of the running process's real and virtual memory usage, in kilobytes.
36
- def mem_usage
37
- a = `ps -o vsz,rss -p #{Process.pid}`.split(/\s+/)[-2..-1].map{|el| el.to_i}
38
- [a.first - a.last, a.last]
39
- end
40
-
41
- inline do |builder|
42
- builder.include '"node.h"' # struct RNode
43
- builder.include '"st.h"' # struct st_table
44
- builder.include '"re.h"' # struct RRegexp
45
- builder.include '"env.h"' # various structs
46
-
47
- builder.prefix <<-EOC
48
- typedef struct RVALUE {
49
- union {
50
- struct {
51
- unsigned long flags; /* always 0 for freed obj */
52
- struct RVALUE *next;
53
- } free;
54
- struct RBasic basic;
55
- struct RObject object;
56
- struct RClass klass;
57
- struct RFloat flonum;
58
- struct RString string;
59
- struct RArray array;
60
- struct RRegexp regexp;
61
- struct RHash hash;
62
- struct RData data;
63
- struct RStruct rstruct;
64
- struct RBignum bignum;
65
- struct RFile file;
66
- struct RNode node;
67
- struct RMatch match;
68
- struct RVarmap varmap;
69
- struct SCOPE scope;
70
- } as;
71
- } RVALUE;
72
-
73
- struct heaps_slot {
74
- void *membase;
75
- RVALUE *slot;
76
- int limit;
77
- };
78
-
79
- struct heaps_slot * rb_gc_heap_slots();
80
- int rb_gc_heaps_used();
81
- int rb_gc_heaps_length();
82
- EOC
83
-
84
- # number of struct heaps_slots used
85
- builder.c <<-EOC
86
- static int
87
- heaps_used() {
88
- return rb_gc_heaps_used();
89
- }
90
- EOC
91
-
92
- # length of the struct heaps_slots allocated
93
- builder.c <<-EOC
94
- static int
95
- heaps_length() {
96
- return rb_gc_heaps_length();
97
- }
98
- EOC
99
-
100
- OBJ_TYPES = ["T_NIL",
101
- "T_OBJECT",
102
- "T_CLASS",
103
- "T_ICLASS",
104
- "T_MODULE",
105
- "T_FLOAT",
106
- "T_STRING",
107
- "T_REGEXP",
108
- "T_ARRAY",
109
- "T_FIXNUM",
110
- "T_HASH",
111
- "T_STRUCT",
112
- "T_BIGNUM",
113
- "T_FILE",
114
- "T_TRUE",
115
- "T_FALSE",
116
- "T_DATA",
117
- "T_SYMBOL",
118
- "T_MATCH"]
119
-
120
- RAW_TYPES = ["T_NONE",
121
- "T_BLKTAG",
122
- "T_UNDEF",
123
- "T_VARMAP",
124
- "T_SCOPE",
125
- "T_NODE"]
126
-
127
- # Counts the live objects on the heap and writes a single tagged YAML frame to the logfile. Set <tt>specials = true</tt> if you also want to count AST nodes and var scopes; otherwise, use <tt>false</tt>.
128
- def snapshot(logfile, tag, specials)
129
- # RDoc stub
130
- end
131
-
132
- builder.c <<-EOC
133
- static void
134
- VALUE snapshot(VALUE logfile, VALUE tag, VALUE _specials) {
135
- Check_Type(logfile, T_STRING);
136
- Check_Type(tag, T_STRING);
137
-
138
- RVALUE *p, *pend;
139
- struct heaps_slot * heaps = rb_gc_heap_slots();
140
-
141
- int specials = RTEST(_specials);
142
-
143
- FILE *obj_log = fopen(StringValueCStr(logfile), "r");
144
- int is_new;
145
- if (!(is_new = (obj_log == NULL)))
146
- fclose(obj_log);
147
-
148
- if ((obj_log = fopen(StringValueCStr(logfile), "a+")) == NULL)
149
- rb_raise(rb_eRuntimeError, "couldn't open snapshot file");
150
-
151
- if (is_new)
152
- fprintf(obj_log, \"---\\n");
153
- fprintf(obj_log, \"- - %i\\n", time(0));
154
- VALUE mem = rb_funcall(self, rb_intern("mem_usage"), 0);
155
- fprintf(obj_log, \" - :\\"memory usage/swap\\": %i\\n", NUM2INT(RARRAY_PTR(mem)[0]));
156
- fprintf(obj_log, \" :\\"memory usage/real\\": %i\\n", NUM2INT(RARRAY_PTR(mem)[1]));
157
-
158
- /* haha */
159
- char tags[#{MAX_UNIQ_TAGS}][#{MAX_TAG_LENGTH}];
160
- char current_tag[2048];
161
- int counts[#{MAX_UNIQ_TAGS}];
162
- int current_pos = 0;
163
-
164
- int filled_slots = 0;
165
- int free_slots = 0;
166
-
167
- int i, j;
168
- for (i = 0; i < rb_gc_heaps_used(); i++) {
169
- p = heaps[i].slot;
170
- pend = p + heaps[i].limit;
171
- for (; p < pend; p++) {
172
- if (p->as.basic.flags) { /* always 0 for freed objects */
173
- filled_slots ++;
174
- sprintf(current_tag, "");
175
- switch (TYPE(p)) {
176
- #{RAW_TYPES.map do |type|
177
- "case #{type}:
178
- if (specials)
179
- sprintf(current_tag , \"%s::::_#{type[2..-1].downcase}\", StringValueCStr(tag));
180
- break;
181
- "
182
- end.flatten.join}
183
- default:
184
- if (!p->as.basic.klass) {
185
- sprintf(current_tag , "%s::::_unknown", StringValueCStr(tag));
186
- } else {
187
- sprintf(current_tag , "%s::::%s", StringValueCStr(tag), rb_obj_classname((VALUE)p));
188
- }
189
- }
190
- if (strlen(current_tag) > #{MAX_TAG_LENGTH})
191
- rb_raise(rb_eRuntimeError, "tag + classname too big; increase MAX_TAG_LENGTH (#{MAX_TAG_LENGTH})");
192
- if (strcmp(current_tag, "")) {
193
- for (j = 0; j < current_pos; j++) {
194
- if (!strcmp(tags[j], current_tag)) {
195
- counts[j] ++;
196
- break;
197
- }
198
- }
199
- if (j == current_pos) {
200
- /* found a new one */
201
- if (current_pos == #{MAX_UNIQ_TAGS})
202
- rb_raise(rb_eRuntimeError, "exhausted tag array; increase MAX_UNIQ_TAGS (#{MAX_UNIQ_TAGS})");
203
- sprintf(tags[current_pos], current_tag);
204
- counts[current_pos] = 1;
205
- current_pos ++;
206
- }
207
- }
208
- } else {
209
- free_slots ++;
210
- }
211
- }
212
- }
213
- fprintf(obj_log, \" :\\"heap usage/filled slots\\": %i\\n", filled_slots);
214
- fprintf(obj_log, \" :\\"heap usage/free slots\\": %i\\n", free_slots);
215
- for (j = 0; j < current_pos; j++) {
216
- fprintf(obj_log, " :\\"%s\\": %i\\n", tags[j], counts[j]);
217
- }
218
- fclose(obj_log);
219
-
220
- /* request GC run */
221
- rb_funcall(rb_mGC, rb_intern("start"), 0);
222
- /* to get a custom module: rb_const_get(parentModule, "ModuleName")
223
- parent module can be something like rb_mKernel for the toplevel */
224
- return Qtrue;
225
- }
226
- EOC
227
- end
228
-
229
- end
230
- end
@@ -1,19 +0,0 @@
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::MEMLOGGER.snapshot(BleakHouse::LOGFILE, 'core rails', BleakHouse::WITH_SPECIALS)
9
- end
10
- alias_method_chain :prepare_application, :bleak_house
11
-
12
- def reset_after_dispatch_with_bleak_house
13
- BleakHouse::MEMLOGGER.snapshot(BleakHouse::LOGFILE, BleakHouse.last_request_name || 'unknown', BleakHouse::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,62 +0,0 @@
1
-
2
- class Gruff::Base
3
-
4
- def draw_legend
5
- @legend_labels = @data.collect {|item| item[DATA_LABEL_INDEX] }
6
-
7
- legend_square_width = @legend_box_size # small square with color of this item
8
- legend_left = 10
9
-
10
- current_x_offset = legend_left
11
- current_y_offset = TOP_MARGIN + TITLE_MARGIN + @title_caps_height + LEGEND_MARGIN
12
-
13
- debug { @d.line 0.0, current_y_offset, @raw_columns, current_y_offset }
14
-
15
- @legend_labels.each_with_index do |legend_label, index|
16
-
17
- next if index > MAX_LEGENDS
18
- legend_label = "some not shown" if index == MAX_LEGENDS
19
-
20
- # Draw label
21
- @d.fill = @font_color
22
- @d.font = @font if @font
23
- @d.pointsize = scale_fontsize(@legend_font_size)
24
- @d.stroke('transparent')
25
- @d.font_weight = NormalWeight
26
- @d.gravity = WestGravity
27
- @d = @d.annotate_scaled( @base_image,
28
- @raw_columns, 1.0,
29
- current_x_offset + (legend_square_width * 1.7), current_y_offset,
30
- legend_label.to_s, @scale)
31
-
32
- if index < MAX_LEGENDS
33
- # Now draw box with color of this dataset
34
- @d = @d.stroke('transparent')
35
- @d = @d.fill @data[index][DATA_COLOR_INDEX]
36
- @d = @d.rectangle(current_x_offset,
37
- current_y_offset - legend_square_width / 2.0,
38
- current_x_offset + legend_square_width,
39
- current_y_offset + legend_square_width / 2.0)
40
- end
41
-
42
- @d.pointsize = @legend_font_size
43
- metrics = @d.get_type_metrics(@base_image, legend_label.to_s)
44
- current_y_offset += metrics.height * 1.05
45
- end
46
- @color_index = 0
47
- end
48
-
49
- alias :setup_graph_measurements_without_top_margin :setup_graph_measurements
50
- def setup_graph_measurements
51
- setup_graph_measurements_without_top_margin
52
- @graph_height += NEGATIVE_TOP_MARGIN
53
- @graph_top -= NEGATIVE_TOP_MARGIN
54
- end
55
-
56
- alias :clip_value_if_greater_than_without_size_hacks :clip_value_if_greater_than
57
- def clip_value_if_greater_than(arg1, arg2)
58
- arg2 = arg2 / 2 if arg1 == @columns / (@norm_data.first[1].size * 2.5)
59
- clip_value_if_greater_than_without_size_hacks(arg1, arg2)
60
- end
61
-
62
- end
@@ -1,25 +0,0 @@
1
-
2
- # http://www.bigbold.com/snippets/posts/show/2032
3
- module Rake
4
- module TaskManager
5
- def redefine_task(task_class, args, &block)
6
- task_name, deps = resolve_args(args)
7
- task_name = task_class.scope_name(@scope, task_name)
8
- deps = [deps] unless deps.respond_to?(:to_ary)
9
- deps = deps.collect {|d| d.to_s }
10
- task = @tasks[task_name.to_s] = task_class.new(task_name, self)
11
- task.application = self
12
- task.add_comment(@last_comment)
13
- @last_comment = nil
14
- task.enhance(deps, &block)
15
- task
16
- end
17
- end
18
- class Task
19
- class << self
20
- def redefine_task(args, &block)
21
- Rake.application.redefine_task(self, args, &block)
22
- end
23
- end
24
- end
25
- end
@@ -1,50 +0,0 @@
1
-
2
- class Array
3
- alias :time :first
4
- alias :data :last
5
-
6
- def sum
7
- inject(0) {|s, x| x + s}
8
- end
9
-
10
- def to_i
11
- self.map{|s| s.to_i}
12
- end
13
-
14
- end
15
-
16
- class Dir
17
- def self.descend path, &block
18
- path = path.split("/") unless path.is_a? Array
19
- top = (path.shift or ".")
20
- Dir.mkdir(top) unless File.exists? top
21
- Dir.chdir(top) do
22
- if path.any?
23
- descend path, &block
24
- else
25
- block.call
26
- end
27
- end
28
- end
29
- end
30
-
31
- class String
32
- def to_filename
33
- self.downcase.gsub(/[^\w\d\-]/, '_')
34
- end
35
- end
36
-
37
- class NilClass
38
- def +(op)
39
- self.to_i + op
40
- end
41
- end
42
-
43
- class Symbol
44
- def =~ regex
45
- self.to_s =~ regex
46
- end
47
- def [](*args)
48
- self.to_s[*args]
49
- end
50
- end
@@ -1,30 +0,0 @@
1
- Index: gc.c
2
- ===================================================================
3
- RCS file: /src/ruby/gc.c,v
4
- retrieving revision 1.168.2.45
5
- diff -p -u -r1.168.2.45 gc.c
6
- --- gc.c 25 Aug 2006 08:12:46 -0000 1.168.2.45
7
- +++ gc.c 31 Aug 2006 18:47:55 -0000
8
- @@ -323,6 +323,22 @@ static struct heaps_slot {
9
- static int heaps_length = 0;
10
- static int heaps_used = 0;
11
-
12
- +struct heaps_slot *
13
- +rb_gc_heap_slots()
14
- +{
15
- + return heaps;
16
- +}
17
- +
18
- +int
19
- +rb_gc_heaps_used() {
20
- + return heaps_used;
21
- +}
22
- +
23
- +int
24
- +rb_gc_heaps_length() {
25
- + return heaps_length;
26
- +}
27
- +
28
- #define HEAP_MIN_SLOTS 10000
29
- static int heap_slots = HEAP_MIN_SLOTS;
30
-