ruby-prof 0.10.8 → 0.11.0.rc1

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.
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__