bleak_house 7.1 → 7.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
-