ruby-prof 0.10.8 → 0.11.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. data/CHANGES +38 -18
  2. data/LICENSE +4 -3
  3. data/README.rdoc +30 -66
  4. data/Rakefile +47 -54
  5. data/bin/ruby-prof +24 -4
  6. data/ext/ruby_prof/extconf.rb +9 -16
  7. data/ext/ruby_prof/rp_call_info.c +369 -0
  8. data/ext/ruby_prof/rp_call_info.h +46 -0
  9. data/ext/ruby_prof/rp_measure.c +48 -0
  10. data/ext/ruby_prof/rp_measure.h +45 -0
  11. data/ext/ruby_prof/rp_measure_allocations.c +86 -0
  12. data/ext/ruby_prof/rp_measure_cpu_time.c +112 -0
  13. data/ext/ruby_prof/rp_measure_gc_runs.c +87 -0
  14. data/ext/ruby_prof/rp_measure_gc_time.c +73 -0
  15. data/ext/ruby_prof/rp_measure_memory.c +81 -0
  16. data/ext/ruby_prof/rp_measure_process_time.c +71 -0
  17. data/ext/ruby_prof/rp_measure_wall_time.c +42 -0
  18. data/ext/ruby_prof/rp_method.c +363 -0
  19. data/ext/ruby_prof/rp_method.h +55 -0
  20. data/ext/ruby_prof/rp_stack.c +61 -0
  21. data/ext/ruby_prof/rp_stack.h +40 -0
  22. data/ext/ruby_prof/rp_thread.c +113 -0
  23. data/ext/ruby_prof/rp_thread.h +20 -0
  24. data/ext/ruby_prof/ruby_prof.c +259 -1398
  25. data/ext/ruby_prof/ruby_prof.h +54 -190
  26. data/ext/ruby_prof/version.h +6 -3
  27. data/lib/1.8/ruby_prof.so +0 -0
  28. data/lib/1.9/ruby_prof.exp +0 -0
  29. data/lib/1.9/ruby_prof.ilk +0 -0
  30. data/lib/1.9/ruby_prof.lib +0 -0
  31. data/lib/1.9/ruby_prof.pdb +0 -0
  32. data/lib/1.9/ruby_prof.so +0 -0
  33. data/lib/ruby-prof.rb +14 -11
  34. data/lib/ruby-prof/abstract_printer.rb +10 -0
  35. data/lib/ruby-prof/aggregate_call_info.rb +2 -0
  36. data/lib/ruby-prof/call_info.rb +2 -0
  37. data/lib/ruby-prof/call_stack_printer.rb +2 -4
  38. data/lib/ruby-prof/call_tree_printer.rb +1 -0
  39. data/lib/ruby-prof/compatibility.rb +134 -0
  40. data/lib/ruby-prof/dot_printer.rb +7 -7
  41. data/lib/ruby-prof/flat_printer.rb +7 -7
  42. data/lib/ruby-prof/flat_printer_with_line_numbers.rb +2 -5
  43. data/lib/ruby-prof/graph_html_printer.rb +4 -2
  44. data/lib/ruby-prof/graph_printer.rb +4 -3
  45. data/lib/ruby-prof/method_info.rb +2 -0
  46. data/lib/ruby-prof/multi_printer.rb +2 -0
  47. data/lib/ruby-prof/{result.rb → profile.rb} +3 -1
  48. data/lib/ruby-prof/rack.rb +1 -0
  49. data/lib/ruby-prof/symbol_to_proc.rb +2 -0
  50. data/lib/ruby-prof/task.rb +1 -0
  51. data/lib/ruby-prof/test.rb +2 -0
  52. data/lib/ruby_prof.exp +0 -0
  53. data/lib/ruby_prof.ilk +0 -0
  54. data/lib/ruby_prof.lib +0 -0
  55. data/lib/ruby_prof.pdb +0 -0
  56. data/lib/ruby_prof.so +0 -0
  57. data/lib/unprof.rb +2 -0
  58. data/test/aggregate_test.rb +8 -8
  59. data/test/basic_test.rb +3 -251
  60. data/test/bug_test.rb +6 -0
  61. data/test/duplicate_names_test.rb +2 -2
  62. data/test/dynamic_method_test.rb +61 -0
  63. data/test/enumerable_test.rb +2 -2
  64. data/test/exceptions_test.rb +4 -3
  65. data/test/exclude_threads_test.rb +2 -2
  66. data/test/exec_test.rb +3 -3
  67. data/test/line_number_test.rb +5 -5
  68. data/test/measure_allocations_test.rb +25 -0
  69. data/test/measure_cpu_time_test.rb +212 -0
  70. data/test/measure_gc_runs_test.rb +29 -0
  71. data/test/measure_gc_time_test.rb +29 -0
  72. data/test/measure_memory_test.rb +36 -0
  73. data/test/measure_process_time_test.rb +205 -0
  74. data/test/measure_wall_time_test.rb +209 -0
  75. data/test/method_elimination_test.rb +2 -2
  76. data/test/module_test.rb +3 -2
  77. data/test/multi_printer_test.rb +2 -2
  78. data/test/no_method_class_test.rb +3 -1
  79. data/test/prime_test.rb +3 -3
  80. data/test/printers_test.rb +106 -8
  81. data/test/recursive_test.rb +7 -6
  82. data/test/singleton_test.rb +2 -2
  83. data/test/stack_printer_test.rb +2 -3
  84. data/test/stack_test.rb +2 -2
  85. data/test/start_stop_test.rb +2 -2
  86. data/test/test_helper.rb +81 -0
  87. data/test/test_suite.rb +34 -29
  88. data/test/thread_test.rb +24 -23
  89. data/test/unique_call_path_test.rb +2 -2
  90. metadata +101 -69
  91. data/ext/ruby_prof/measure_allocations.h +0 -83
  92. data/ext/ruby_prof/measure_cpu_time.h +0 -152
  93. data/ext/ruby_prof/measure_gc_runs.h +0 -76
  94. data/ext/ruby_prof/measure_gc_time.h +0 -57
  95. data/ext/ruby_prof/measure_memory.h +0 -101
  96. data/ext/ruby_prof/measure_process_time.h +0 -63
  97. data/ext/ruby_prof/measure_wall_time.h +0 -53
  98. data/ext/ruby_prof/mingw/Rakefile +0 -23
  99. data/ext/ruby_prof/mingw/build.rake +0 -38
  100. data/rails/environment/profile.rb +0 -24
  101. data/rails/example/example_test.rb +0 -9
  102. data/rails/profile_test_helper.rb +0 -21
  103. data/test/current_failures_windows +0 -8
  104. data/test/measurement_test.rb +0 -132
  105. data/test/ruby-prof-bin +0 -20
@@ -1,17 +1,12 @@
1
1
  require "mkmf"
2
2
 
3
- if RUBY_VERSION >= "1.9"
4
- if RUBY_RELEASE_DATE < "2005-03-17"
5
- STDERR.print("Ruby version is too old\n")
6
- exit(1)
7
- end
8
- elsif RUBY_VERSION >= "1.8"
9
- if RUBY_RELEASE_DATE < "2005-03-22"
10
- STDERR.print("Ruby version is too old\n")
11
- exit(1)
12
- end
13
- else
14
- STDERR.print("Ruby version is too old\n")
3
+ if RUBY_VERSION == "1.8.6"
4
+ STDERR.print("Ruby #{RUBY_VERSION} is no longer supported. Please upgrade to 1.8.7 or 1.9.2 or higher\n")
5
+ exit(1)
6
+ end
7
+
8
+ if RUBY_VERSION == "1.9.0" or RUBY_VERSION == "1.9.1"
9
+ STDERR.print("Ruby #{RUBY_VERSION} is no longer supported. Please upgrade to 1.9.2 or higher\n")
15
10
  exit(1)
16
11
  end
17
12
 
@@ -30,9 +25,6 @@ have_func("rb_class_superclass")
30
25
  have_func("rb_heap_total_mem")
31
26
  have_func("rb_gc_heap_info")
32
27
 
33
- # Ruby 1.9 unexposed methods
34
- have_func("rb_gc_malloc_allocations")
35
- have_func("rb_gc_malloc_allocated_size")
36
28
 
37
29
  def add_define(name, value = nil)
38
30
  if value
@@ -41,6 +33,7 @@ def add_define(name, value = nil)
41
33
  $defs.push("-D#{name}")
42
34
  end
43
35
  end
36
+
44
37
  require 'rubygems'
45
38
  unless Gem.win_platform? || RUBY_PLATFORM =~ /darwin/
46
39
  $LDFLAGS += " -lrt" # for clock_gettime
@@ -57,4 +50,4 @@ if RUBY_VERSION > "1.9"
57
50
  add_define("THREADS_INHERIT_EVENT_FLAGS", (threads.size == 2) ? "1" : "0")
58
51
  end
59
52
 
60
- create_makefile("ruby_prof_ext")
53
+ create_makefile("ruby_prof")
@@ -0,0 +1,369 @@
1
+ /* Copyright (C) 2005-2011 Shugo Maeda <shugo@ruby-lang.org> and Charlie Savage <cfis@savagexi.com>
2
+ Please see the LICENSE file for copyright and distribution information */
3
+
4
+ #include "ruby_prof.h"
5
+
6
+ #define INITIAL_CALL_INFOS_SIZE 2
7
+
8
+ VALUE cCallInfo;
9
+
10
+ /* ======= Call Info ========*/
11
+ st_table *
12
+ call_info_table_create()
13
+ {
14
+ return st_init_table(&type_method_hash);
15
+ }
16
+
17
+ size_t
18
+ call_info_table_insert(st_table *table, const prof_method_key_t *key, prof_call_info_t *val)
19
+ {
20
+ return st_insert(table, (st_data_t) key, (st_data_t) val);
21
+ }
22
+
23
+ prof_call_info_t *
24
+ call_info_table_lookup(st_table *table, const prof_method_key_t *key)
25
+ {
26
+ st_data_t val;
27
+ if (st_lookup(table, (st_data_t) key, &val))
28
+ {
29
+ return (prof_call_info_t *) val;
30
+ }
31
+ else
32
+ {
33
+ return NULL;
34
+ }
35
+ }
36
+
37
+ static void
38
+ call_info_table_free(st_table *table)
39
+ {
40
+ st_free_table(table);
41
+ }
42
+
43
+ /* Document-class: RubyProf::CallInfo
44
+ RubyProf::CallInfo is a helper class used by RubyProf::MethodInfo
45
+ to keep track of which child methods were called and how long
46
+ they took to execute. */
47
+
48
+ /* :nodoc: */
49
+ prof_call_info_t *
50
+ prof_call_info_create(prof_method_t* method, prof_call_info_t* parent)
51
+ {
52
+ prof_call_info_t *result = ALLOC(prof_call_info_t);
53
+ result->object = Qnil;
54
+ result->target = method;
55
+ result->parent = parent;
56
+ result->call_infos = call_info_table_create();
57
+ result->children = Qnil;
58
+
59
+ result->called = 0;
60
+ result->total_time = 0;
61
+ result->self_time = 0;
62
+ result->wait_time = 0;
63
+ result->line = 0;
64
+ return result;
65
+ }
66
+
67
+ static void
68
+ prof_call_info_mark(prof_call_info_t *call_info)
69
+ {
70
+ {
71
+ VALUE target = call_info->target->object;
72
+ if (NIL_P(target))
73
+ prof_method_mark(call_info->target);
74
+ else
75
+ rb_gc_mark(target);
76
+ }
77
+ rb_gc_mark(call_info->children);
78
+ if (call_info->parent) {
79
+ VALUE parent = call_info->parent->object;
80
+ if (NIL_P(parent)) {
81
+ prof_call_info_mark(call_info->parent);
82
+ }
83
+ else {
84
+ rb_gc_mark(parent);
85
+ }
86
+ }
87
+ }
88
+
89
+ static void
90
+ prof_call_info_free(prof_call_info_t *call_info)
91
+ {
92
+ call_info_table_free(call_info->call_infos);
93
+ xfree(call_info);
94
+ }
95
+
96
+ static VALUE
97
+ prof_call_info_wrap(prof_call_info_t *call_info)
98
+ {
99
+ if (call_info->object == Qnil)
100
+ {
101
+ call_info->object = Data_Wrap_Struct(cCallInfo, prof_call_info_mark, prof_call_info_free, call_info);
102
+ }
103
+ return call_info->object;
104
+ }
105
+
106
+ static prof_call_info_t *
107
+ prof_get_call_info_result(VALUE obj)
108
+ {
109
+ if (BUILTIN_TYPE(obj) != T_DATA)
110
+ {
111
+ /* Should never happen */
112
+ rb_raise(rb_eTypeError, "Not a call info object");
113
+ }
114
+ return (prof_call_info_t *) DATA_PTR(obj);
115
+ }
116
+
117
+
118
+ /* call-seq:
119
+ called -> MethodInfo
120
+
121
+ Returns the target method. */
122
+ static VALUE
123
+ prof_call_info_target(VALUE self)
124
+ {
125
+ /* Target is a pointer to a method_info - so we have to be careful
126
+ about the GC. We will wrap the method_info but provide no
127
+ free method so the underlying object is not freed twice! */
128
+
129
+ prof_call_info_t *result = prof_get_call_info_result(self);
130
+ return prof_method_wrap(result->target);
131
+ }
132
+
133
+ /* call-seq:
134
+ called -> int
135
+
136
+ Returns the total amount of times this method was called. */
137
+ static VALUE
138
+ prof_call_info_called(VALUE self)
139
+ {
140
+ prof_call_info_t *result = prof_get_call_info_result(self);
141
+ return INT2NUM(result->called);
142
+ }
143
+
144
+ /* call-seq:
145
+ called=n -> n
146
+
147
+ Sets the call count to n. */
148
+ static VALUE
149
+ prof_call_info_set_called(VALUE self, VALUE called)
150
+ {
151
+ prof_call_info_t *result = prof_get_call_info_result(self);
152
+ result->called = NUM2INT(called);
153
+ return called;
154
+ }
155
+
156
+ /* call-seq:
157
+ line_no -> int
158
+
159
+ returns the line number of the method */
160
+ static VALUE
161
+ prof_call_info_line(VALUE self)
162
+ {
163
+ prof_call_info_t *result = prof_get_call_info_result(self);
164
+ return rb_int_new(result->line);
165
+ }
166
+
167
+ /* call-seq:
168
+ total_time -> float
169
+
170
+ Returns the total amount of time spent in this method and its children. */
171
+ static VALUE
172
+ prof_call_info_total_time(VALUE self)
173
+ {
174
+ prof_call_info_t *result = prof_get_call_info_result(self);
175
+ return rb_float_new(result->total_time);
176
+ }
177
+
178
+ /* call-seq:
179
+ add_total_time(call_info) -> nil
180
+
181
+ adds total time time from call_info to self. */
182
+ static VALUE
183
+ prof_call_info_add_total_time(VALUE self, VALUE other)
184
+ {
185
+ prof_call_info_t *result = prof_get_call_info_result(self);
186
+ prof_call_info_t *other_info = prof_get_call_info_result(other);
187
+
188
+ result->total_time += other_info->total_time;
189
+ return Qnil;
190
+ }
191
+
192
+ /* call-seq:
193
+ self_time -> float
194
+
195
+ Returns the total amount of time spent in this method. */
196
+ static VALUE
197
+ prof_call_info_self_time(VALUE self)
198
+ {
199
+ prof_call_info_t *result = prof_get_call_info_result(self);
200
+
201
+ return rb_float_new(result->self_time);
202
+ }
203
+
204
+ /* call-seq:
205
+ add_self_time(call_info) -> nil
206
+
207
+ adds self time from call_info to self. */
208
+ static VALUE
209
+ prof_call_info_add_self_time(VALUE self, VALUE other)
210
+ {
211
+ prof_call_info_t *result = prof_get_call_info_result(self);
212
+ prof_call_info_t *other_info = prof_get_call_info_result(other);
213
+
214
+ result->self_time += other_info->self_time;
215
+ return Qnil;
216
+ }
217
+
218
+ /* call-seq:
219
+ wait_time -> float
220
+
221
+ Returns the total amount of time this method waited for other threads. */
222
+ static VALUE
223
+ prof_call_info_wait_time(VALUE self)
224
+ {
225
+ prof_call_info_t *result = prof_get_call_info_result(self);
226
+
227
+ return rb_float_new(result->wait_time);
228
+ }
229
+
230
+ /* call-seq:
231
+ add_wait_time(call_info) -> nil
232
+
233
+ adds wait time from call_info to self. */
234
+
235
+ static VALUE
236
+ prof_call_info_add_wait_time(VALUE self, VALUE other)
237
+ {
238
+ prof_call_info_t *result = prof_get_call_info_result(self);
239
+ prof_call_info_t *other_info = prof_get_call_info_result(other);
240
+
241
+ result->wait_time += other_info->wait_time;
242
+ return Qnil;
243
+ }
244
+
245
+ /* call-seq:
246
+ parent -> call_info
247
+
248
+ Returns the call_infos parent call_info object (the method that called this method).*/
249
+ static VALUE
250
+ prof_call_info_parent(VALUE self)
251
+ {
252
+ prof_call_info_t *result = prof_get_call_info_result(self);
253
+ if (result->parent)
254
+ return prof_call_info_wrap(result->parent);
255
+ else
256
+ return Qnil;
257
+ }
258
+
259
+ /* call-seq:
260
+ parent=new_parent -> new_parent
261
+
262
+ Changes the parent of self to new_parent and returns it.*/
263
+ static VALUE
264
+ prof_call_info_set_parent(VALUE self, VALUE new_parent)
265
+ {
266
+ prof_call_info_t *result = prof_get_call_info_result(self);
267
+ if (new_parent == Qnil)
268
+ result->parent = NULL;
269
+ else
270
+ result->parent = prof_get_call_info_result(new_parent);
271
+ return prof_call_info_parent(self);
272
+ }
273
+
274
+ static int
275
+ prof_call_info_collect_children(st_data_t key, st_data_t value, st_data_t result)
276
+ {
277
+ prof_call_info_t *call_info = (prof_call_info_t *) value;
278
+ VALUE arr = (VALUE) result;
279
+ rb_ary_push(arr, prof_call_info_wrap(call_info));
280
+ return ST_CONTINUE;
281
+ }
282
+
283
+ /* call-seq:
284
+ children -> hash
285
+
286
+ Returns an array of call info objects of methods that this method
287
+ called (ie, children).*/
288
+ static VALUE
289
+ prof_call_info_children(VALUE self)
290
+ {
291
+ prof_call_info_t *call_info = prof_get_call_info_result(self);
292
+ if (call_info->children == Qnil)
293
+ {
294
+ call_info->children = rb_ary_new();
295
+ st_foreach(call_info->call_infos, prof_call_info_collect_children, call_info->children);
296
+ }
297
+ return call_info->children;
298
+ }
299
+
300
+ /* ======= Call Infos ========*/
301
+ prof_call_infos_t*
302
+ prof_call_infos_create()
303
+ {
304
+ prof_call_infos_t *result = ALLOC(prof_call_infos_t);
305
+ result->start = ALLOC_N(prof_call_info_t*, INITIAL_CALL_INFOS_SIZE);
306
+ result->end = result->start + INITIAL_CALL_INFOS_SIZE;
307
+ result->ptr = result->start;
308
+ result->object = Qnil;
309
+ return result;
310
+ }
311
+
312
+ void
313
+ prof_call_infos_free(prof_call_infos_t *call_infos)
314
+ {
315
+ xfree(call_infos->start);
316
+ xfree(call_infos);
317
+ }
318
+
319
+ void
320
+ prof_add_call_info(prof_call_infos_t *call_infos, prof_call_info_t *call_info)
321
+ {
322
+ if (call_infos->ptr == call_infos->end)
323
+ {
324
+ size_t len = call_infos->ptr - call_infos->start;
325
+ size_t new_capacity = (call_infos->end - call_infos->start) * 2;
326
+ REALLOC_N(call_infos->start, prof_call_info_t*, new_capacity);
327
+ call_infos->ptr = call_infos->start + len;
328
+ call_infos->end = call_infos->start + new_capacity;
329
+ }
330
+ *call_infos->ptr = call_info;
331
+ call_infos->ptr++;
332
+ }
333
+
334
+ VALUE
335
+ prof_call_infos_wrap(prof_call_infos_t *call_infos)
336
+ {
337
+ if (call_infos->object == Qnil)
338
+ {
339
+ prof_call_info_t **i;
340
+ call_infos->object = rb_ary_new();
341
+ for(i=call_infos->start; i<call_infos->ptr; i++)
342
+ {
343
+ VALUE call_info = prof_call_info_wrap(*i);
344
+ rb_ary_push(call_infos->object, call_info);
345
+ }
346
+ }
347
+ return call_infos->object;
348
+ }
349
+
350
+
351
+ void rp_init_call_info()
352
+ {
353
+ /* CallInfo */
354
+ cCallInfo = rb_define_class_under(mProf, "CallInfo", rb_cObject);
355
+ rb_undef_method(CLASS_OF(cCallInfo), "new");
356
+ rb_define_method(cCallInfo, "parent", prof_call_info_parent, 0);
357
+ rb_define_method(cCallInfo, "parent=", prof_call_info_set_parent, 1);
358
+ rb_define_method(cCallInfo, "children", prof_call_info_children, 0);
359
+ rb_define_method(cCallInfo, "target", prof_call_info_target, 0);
360
+ rb_define_method(cCallInfo, "called", prof_call_info_called, 0);
361
+ rb_define_method(cCallInfo, "called=", prof_call_info_set_called, 1);
362
+ rb_define_method(cCallInfo, "total_time", prof_call_info_total_time, 0);
363
+ rb_define_method(cCallInfo, "add_total_time", prof_call_info_add_total_time, 1);
364
+ rb_define_method(cCallInfo, "self_time", prof_call_info_self_time, 0);
365
+ rb_define_method(cCallInfo, "add_self_time", prof_call_info_add_self_time, 1);
366
+ rb_define_method(cCallInfo, "wait_time", prof_call_info_wait_time, 0);
367
+ rb_define_method(cCallInfo, "add_wait_time", prof_call_info_add_wait_time, 1);
368
+ rb_define_method(cCallInfo, "line", prof_call_info_line, 0);
369
+ }
@@ -0,0 +1,46 @@
1
+ /* Copyright (C) 2005-2011 Shugo Maeda <shugo@ruby-lang.org> and Charlie Savage <cfis@savagexi.com>
2
+ Please see the LICENSE file for copyright and distribution information */
3
+
4
+ #ifndef __RP_CALL_INFO_H__
5
+ #define __RP_CALL_INFO_H__
6
+
7
+ #include "rp_measure.h"
8
+ #include "rp_method.h"
9
+
10
+ extern VALUE cCallInfo;
11
+
12
+ /* Callers and callee information for a method. */
13
+ typedef struct prof_call_info_t
14
+ {
15
+ prof_method_t *target; /* Use target instead of method to avoid conflict with Ruby method */
16
+ struct prof_call_info_t *parent;
17
+ st_table *call_infos;
18
+ int called;
19
+ double total_time;
20
+ double self_time;
21
+ double wait_time;
22
+ int line;
23
+ VALUE object;
24
+ VALUE children;
25
+ } prof_call_info_t;
26
+
27
+ /* Array of call_info objects */
28
+ typedef struct prof_call_infos_t
29
+ {
30
+ prof_call_info_t **start;
31
+ prof_call_info_t **end;
32
+ prof_call_info_t **ptr;
33
+ VALUE object;
34
+ } prof_call_infos_t;
35
+
36
+
37
+ void rp_init_call_info(void);
38
+ prof_call_infos_t* prof_call_infos_create();
39
+ void prof_call_infos_free(prof_call_infos_t *call_infos);
40
+ void prof_add_call_info(prof_call_infos_t *call_infos, prof_call_info_t *call_info);
41
+ VALUE prof_call_infos_wrap(prof_call_infos_t *call_infos);
42
+ prof_call_info_t * prof_call_info_create(prof_method_t* method, prof_call_info_t* parent);
43
+ prof_call_info_t * call_info_table_lookup(st_table *table, const prof_method_key_t *key);
44
+ size_t call_info_table_insert(st_table *table, const prof_method_key_t *key, prof_call_info_t *val);
45
+
46
+ #endif //__RP_CALL_INFO_H__