ruby-prof 0.13.1 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +14 -0
  3. data/README.rdoc +1 -1
  4. data/Rakefile +2 -3
  5. data/bin/ruby-prof +4 -4
  6. data/bin/ruby-prof-check-trace +45 -0
  7. data/doc/LICENSE.html +49 -88
  8. data/doc/README_rdoc.html +92 -106
  9. data/doc/Rack.html +47 -116
  10. data/doc/Rack/RubyProf.html +119 -174
  11. data/doc/RubyProf.html +184 -216
  12. data/doc/RubyProf/AbstractPrinter.html +131 -162
  13. data/doc/RubyProf/AggregateCallInfo.html +136 -166
  14. data/doc/RubyProf/CallInfo.html +113 -154
  15. data/doc/RubyProf/CallInfoPrinter.html +56 -123
  16. data/doc/RubyProf/CallInfoVisitor.html +87 -216
  17. data/doc/RubyProf/CallStackPrinter.html +222 -215
  18. data/doc/RubyProf/CallTreePrinter.html +91 -142
  19. data/doc/RubyProf/Cmd.html +115 -157
  20. data/doc/RubyProf/DotPrinter.html +88 -140
  21. data/doc/RubyProf/FlatPrinter.html +66 -129
  22. data/doc/RubyProf/FlatPrinterWithLineNumbers.html +69 -132
  23. data/doc/RubyProf/GraphHtmlPrinter.html +115 -166
  24. data/doc/RubyProf/GraphPrinter.html +58 -125
  25. data/doc/RubyProf/MethodInfo.html +147 -172
  26. data/doc/RubyProf/MultiPrinter.html +104 -150
  27. data/doc/RubyProf/Profile.html +125 -179
  28. data/doc/RubyProf/ProfileTask.html +117 -157
  29. data/doc/RubyProf/Test.html +115 -154
  30. data/doc/RubyProf/Thread.html +87 -147
  31. data/doc/created.rid +13 -14
  32. data/doc/examples/flat_txt.html +51 -90
  33. data/doc/examples/graph_html.html +852 -0
  34. data/doc/examples/graph_txt.html +64 -92
  35. data/doc/fonts.css +167 -0
  36. data/doc/fonts/Lato-Light.ttf +0 -0
  37. data/doc/fonts/Lato-LightItalic.ttf +0 -0
  38. data/doc/fonts/Lato-Regular.ttf +0 -0
  39. data/doc/fonts/Lato-RegularItalic.ttf +0 -0
  40. data/doc/fonts/SourceCodePro-Bold.ttf +0 -0
  41. data/doc/fonts/SourceCodePro-Regular.ttf +0 -0
  42. data/doc/images/add.png +0 -0
  43. data/doc/images/arrow_up.png +0 -0
  44. data/doc/images/delete.png +0 -0
  45. data/doc/images/tag_blue.png +0 -0
  46. data/doc/index.html +75 -65
  47. data/doc/js/darkfish.js +0 -15
  48. data/doc/js/search.js +20 -5
  49. data/doc/js/search_index.js +1 -1
  50. data/doc/rdoc.css +255 -218
  51. data/doc/table_of_contents.html +751 -353
  52. data/ext/ruby_prof/extconf.rb +20 -22
  53. data/ext/ruby_prof/rp_measure_allocations.c +9 -5
  54. data/ext/ruby_prof/rp_measure_gc_runs.c +8 -0
  55. data/ext/ruby_prof/rp_measure_gc_time.c +5 -2
  56. data/ext/ruby_prof/rp_measure_wall_time.c +1 -0
  57. data/ext/ruby_prof/rp_method.c +0 -9
  58. data/ext/ruby_prof/rp_method.h +1 -6
  59. data/ext/ruby_prof/ruby_prof.c +32 -112
  60. data/ext/ruby_prof/ruby_prof.h +9 -10
  61. data/lib/ruby-prof.rb +2 -1
  62. data/lib/ruby-prof/aggregate_call_info.rb +4 -6
  63. data/lib/ruby-prof/call_info_visitor.rb +42 -44
  64. data/lib/ruby-prof/printers/graph_html_printer.rb +0 -8
  65. data/lib/ruby-prof/profile.rb +4 -4
  66. data/lib/ruby-prof/rack.rb +47 -47
  67. data/lib/ruby-prof/task.rb +0 -0
  68. data/lib/ruby-prof/thread.rb +22 -22
  69. data/lib/ruby-prof/version.rb +3 -0
  70. data/ruby-prof.gemspec +7 -11
  71. data/test/call_info_test.rb +78 -78
  72. data/test/call_info_visitor_test.rb +31 -31
  73. data/test/fiber_test.rb +2 -2
  74. data/test/measure_gc_runs_test.rb +1 -1
  75. data/test/measure_process_time_test.rb +7 -6
  76. data/test/printers_test.rb +4 -8
  77. data/test/recursive_test.rb +5 -9
  78. data/test/test_helper.rb +1 -1
  79. data/test/unique_call_path_test.rb +7 -29
  80. data/test/yarv_test.rb +55 -0
  81. metadata +63 -55
  82. data/ext/ruby_prof/version.h +0 -7
  83. data/lib/ruby-prof/test.rb +0 -150
  84. data/test/exec_test.rb +0 -14
  85. data/test/test_suite.rb +0 -37
@@ -1,33 +1,32 @@
1
1
  require "mkmf"
2
2
 
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")
3
+ if RUBY_VERSION < "1.9.3"
4
+ STDERR.puts("Ruby version #{RUBY_VERSION} is no longer supported. Please upgrade to 1.9.3 or higher")
10
5
  exit(1)
11
6
  end
12
7
 
13
8
  have_header("sys/times.h")
14
9
 
15
- # Stefan Kaes / Alexander Dymo GC patch
10
+ # standard ruby methods
11
+ have_func("rb_gc_stat")
12
+ have_func("rb_gc_count")
13
+
14
+ # Alexander Dymo GC patch
16
15
  have_func("rb_os_allocated_objects")
17
16
  have_func("rb_gc_allocated_size")
17
+
18
+ # Stefan Kaes GC patches
18
19
  have_func("rb_gc_collections")
19
20
  have_func("rb_gc_time")
20
-
21
- # 1.9.3 superclass
22
- have_func("rb_class_superclass")
21
+ # for ruby 2.1
22
+ have_func("rb_gc_total_time")
23
+ have_func("rb_gc_total_mallocs")
24
+ have_func("rb_gc_total_malloced_bytes")
23
25
 
24
26
  # Lloyd Hilaiel's heap info patch
25
27
  have_func("rb_heap_total_mem")
26
28
  have_func("rb_gc_heap_info")
27
29
 
28
- # whether our ruby has fibers
29
- have_func("rb_fiber_current")
30
-
31
30
  def add_define(name, value = nil)
32
31
  if value
33
32
  $defs.push("-D#{name}=#{value}")
@@ -36,24 +35,23 @@ def add_define(name, value = nil)
36
35
  end
37
36
  end
38
37
 
39
- # if have_func("rb_gc_enable_stats")
40
- # add_define("TOGGLE_GC_STATS", 1)
41
- # end
42
-
43
- require 'rubygems'
44
- unless Gem.win_platform? || RUBY_PLATFORM =~ /(darwin|openbsd)/
38
+ if !Gem.win_platform? && RUBY_PLATFORM !~ /(darwin|openbsd)/
45
39
  $LDFLAGS += " -lrt" # for clock_gettime
46
40
  end
47
41
  add_define("RUBY_VERSION", RUBY_VERSION.gsub('.', ''))
48
42
 
49
- # for ruby 1.9, determine whether threads inherit trace flags (latest 1.9.2 works correctly)
43
+ # for ruby 1.9, determine whether threads inherit trace flags (latest 1.9.2 and later should work correctly)
50
44
  if RUBY_VERSION > "1.9"
51
45
  require 'set'
52
46
  threads = Set.new
53
47
  set_trace_func lambda { |*args| threads << Thread.current.object_id }
54
48
  Thread.new{1}.join
55
49
  set_trace_func nil
56
- add_define("THREADS_INHERIT_EVENT_FLAGS", (threads.size == 2) ? "1" : "0")
50
+ if threads.size < 2
51
+ # if we end up here, ruby does not automatically active tracing in spawned threads
52
+ STDERR.puts("Ruby #{RUBY_VERSION} does not activate tracing in spawned threads. Consider upgrading.")
53
+ exit(1)
54
+ end
57
55
  end
58
56
 
59
57
  create_makefile("ruby_prof")
@@ -11,8 +11,8 @@ static VALUE cMeasureAllocations;
11
11
  unsigned LONG_LONG rb_os_allocated_objects();
12
12
  #endif
13
13
 
14
- #if defined(HAVE_RB_GC_MALLOC_ALLOCATIONS)
15
- unsigned LONG_LONG rb_gc_malloc_allocations();
14
+ #if defined(HAVE_RB_GC_STAT)
15
+ size_t rb_gc_stat(VALUE key);
16
16
  #endif
17
17
 
18
18
  static double
@@ -22,9 +22,13 @@ measure_allocations()
22
22
  #define MEASURE_ALLOCATIONS_ENABLED Qtrue
23
23
  return rb_os_allocated_objects();
24
24
 
25
- #elif defined(HAVE_RB_GC_MALLOC_ALLOCATIONS)
25
+ #elif defined(HAVE_RB_GC_STAT) && RUBY_VERSION == 210
26
26
  #define MEASURE_ALLOCATIONS_ENABLED Qtrue
27
- return rb_gc_malloc_allocations();
27
+ static VALUE total_alloc_symbol = 0;
28
+ if (!total_alloc_symbol) {
29
+ total_alloc_symbol = ID2SYM(rb_intern_const("total_allocated_object"));
30
+ }
31
+ return rb_gc_stat(total_alloc_symbol);
28
32
 
29
33
  #else
30
34
  #define MEASURE_ALLOCATIONS_ENABLED Qfalse
@@ -61,5 +65,5 @@ void rp_init_measure_allocations()
61
65
  rb_define_const(mProf, "ALLOCATIONS_ENABLED", MEASURE_ALLOCATIONS_ENABLED);
62
66
 
63
67
  cMeasureAllocations = rb_define_class_under(mMeasure, "Allocations", rb_cObject);
64
- rb_define_singleton_method(cMeasureAllocations, "measure", prof_measure_allocations, 0);
68
+ rb_define_singleton_method(cMeasureAllocations, "measure", prof_measure_allocations, 0);
65
69
  }
@@ -11,6 +11,10 @@ static VALUE cMeasureGcRuns;
11
11
  VALUE rb_gc_collections(void);
12
12
  #endif
13
13
 
14
+ #if defined(HAVE_RB_GC_COUNT)
15
+ size_t rb_gc_count(void);
16
+ #endif
17
+
14
18
  #if defined(HAVE_RB_GC_HEAP_INFO)
15
19
  VALUE rb_gc_heap_info(void);
16
20
  #endif
@@ -23,6 +27,10 @@ measure_gc_runs()
23
27
  #define MEASURE_GC_RUNS_ENABLED Qtrue
24
28
  return NUM2INT(rb_gc_collections());
25
29
 
30
+ #elif defined(HAVE_RB_GC_COUNT)
31
+ #define MEASURE_GC_RUNS_ENABLED Qtrue
32
+ return rb_gc_count();
33
+
26
34
  #elif defined(HAVE_RB_GC_HEAP_INFO)
27
35
  #define MEASURE_GC_RUNS_ENABLED Qtrue
28
36
  VALUE h = rb_gc_heap_info();
@@ -11,11 +11,14 @@ static VALUE cMeasureGcTimes;
11
11
  VALUE rb_gc_time();
12
12
  #endif
13
13
 
14
-
15
14
  static double
16
15
  measure_gc_time()
17
16
  {
18
- #if defined(HAVE_RB_GC_TIME)
17
+ #if defined(HAVE_RB_GC_TOTAL_TIME)
18
+ #define MEASURE_GC_TIME_ENABLED Qtrue
19
+ return rb_gc_total_time();
20
+
21
+ #elif defined(HAVE_RB_GC_TIME)
19
22
  #define MEASURE_GC_TIME_ENABLED Qtrue
20
23
  const double conversion = 1000000.0;
21
24
  #if HAVE_LONG_LONG
@@ -3,6 +3,7 @@
3
3
 
4
4
  /* :nodoc: */
5
5
  #include "ruby_prof.h"
6
+ #include <sys/time.h>
6
7
 
7
8
  static VALUE cMeasureWallTime;
8
9
 
@@ -37,16 +37,7 @@ figure_singleton_name(VALUE klass)
37
37
  /* Make sure to get the super class so that we don't
38
38
  mistakenly grab a T_ICLASS which would lead to
39
39
  unknown method errors. */
40
- #ifdef HAVE_RB_CLASS_SUPERCLASS
41
- // 1.9.3
42
40
  VALUE super = rb_class_superclass(klass);
43
- #else
44
- # ifdef RCLASS_SUPER
45
- VALUE super = rb_class_real(RCLASS_SUPER(klass));
46
- # else
47
- VALUE super = rb_class_real(RCLASS(klass)->super);
48
- # endif
49
- #endif
50
41
  result = rb_str_new2("<Object::");
51
42
  rb_str_append(result, rb_inspect(super));
52
43
  rb_str_cat2(result, ">");
@@ -6,15 +6,10 @@
6
6
 
7
7
  #include <ruby.h>
8
8
 
9
- #ifndef RUBY_VM
10
- #include <st.h>
11
- typedef st_data_t st_index_t;
12
- #endif
13
-
14
9
  extern VALUE cMethodInfo;
15
10
 
16
11
  /* A key used to identify each method */
17
- typedef struct
12
+ typedef struct
18
13
  {
19
14
  VALUE klass; /* The method's class. */
20
15
  ID mid; /* The method id. */
@@ -29,12 +29,6 @@
29
29
  VALUE mProf;
30
30
  VALUE cProfile;
31
31
 
32
- #ifndef RUBY_VM
33
- /* Global variable to hold current profile - needed
34
- prior to Ruby 1.9 */
35
- static prof_profile_t* pCurrentProfile;
36
- #endif
37
-
38
32
  static prof_profile_t*
39
33
  prof_get_profile(VALUE self)
40
34
  {
@@ -50,35 +44,29 @@ prof_get_profile(VALUE self)
50
44
  */
51
45
  static FILE* trace_file = NULL;
52
46
 
53
- /* Copied from eval.c (1.8.x) / thread.c (1.9.2) */
47
+ /* Copied from thread.c (1.9.3) */
54
48
  static const char *
55
49
  get_event_name(rb_event_flag_t event)
56
50
  {
57
51
  switch (event) {
58
- case RUBY_EVENT_LINE:
59
- return "line";
60
- case RUBY_EVENT_CLASS:
61
- return "class";
62
- case RUBY_EVENT_END:
63
- return "end";
64
- case RUBY_EVENT_CALL:
65
- return "call";
66
- case RUBY_EVENT_RETURN:
67
- return "return";
68
- case RUBY_EVENT_C_CALL:
69
- return "c-call";
70
- case RUBY_EVENT_C_RETURN:
71
- return "c-return";
72
- case RUBY_EVENT_RAISE:
73
- return "raise";
74
-
75
- #ifdef RUBY_VM
76
- case RUBY_EVENT_SWITCH:
77
- return "thread-interrupt";
78
- #endif
79
-
80
- default:
81
- return "unknown";
52
+ case RUBY_EVENT_LINE:
53
+ return "line";
54
+ case RUBY_EVENT_CLASS:
55
+ return "class";
56
+ case RUBY_EVENT_END:
57
+ return "end";
58
+ case RUBY_EVENT_CALL:
59
+ return "call";
60
+ case RUBY_EVENT_RETURN:
61
+ return "return";
62
+ case RUBY_EVENT_C_CALL:
63
+ return "c-call";
64
+ case RUBY_EVENT_C_RETURN:
65
+ return "c-return";
66
+ case RUBY_EVENT_RAISE:
67
+ return "raise";
68
+ default:
69
+ return "unknown";
82
70
  }
83
71
  }
84
72
 
@@ -97,11 +85,7 @@ create_method(rb_event_flag_t event, VALUE klass, ID mid, const char* source_fil
97
85
 
98
86
 
99
87
  static prof_method_t*
100
- #ifdef RUBY_VM
101
- get_method(rb_event_flag_t event, VALUE klass, ID mid, thread_data_t* thread_data)
102
- # else
103
- get_method(rb_event_flag_t event, NODE *node, VALUE klass, ID mid, thread_data_t* thread_data)
104
- #endif
88
+ get_method(rb_event_flag_t event, VALUE klass, ID mid, thread_data_t* thread_data)
105
89
  {
106
90
  prof_method_key_t key;
107
91
  prof_method_t *method = NULL;
@@ -147,24 +131,15 @@ prof_pop_threads(prof_profile_t* profile)
147
131
  }
148
132
 
149
133
  /* =========== Profiling ================= */
150
- #ifdef RUBY_VM
151
134
  static void
152
135
  prof_trace(prof_profile_t* profile, rb_event_flag_t event, ID mid, VALUE klass, double measurement)
153
- #else
154
- static void
155
- prof_trace(prof_profile_t* profile, rb_event_flag_t event, NODE *node, ID mid, VALUE klass, double measurement)
156
- #endif
157
136
  {
158
137
  static VALUE last_fiber_id = Qnil;
159
138
 
160
139
  VALUE thread = rb_thread_current();
161
140
  VALUE thread_id = rb_obj_id(thread);
162
- #if defined(HAVE_RB_FIBER_CURRENT)
163
141
  VALUE fiber = rb_fiber_current();
164
142
  VALUE fiber_id = rb_obj_id(fiber);
165
- #else
166
- VALUE fiber_id = thread_id;
167
- #endif
168
143
  const char* class_name = NULL;
169
144
  const char* method_name = rb_id2name(mid);
170
145
  const char* source_file = rb_sourcefile();
@@ -189,20 +164,10 @@ prof_trace(prof_profile_t* profile, rb_event_flag_t event, NODE *node, ID mid, V
189
164
  last_fiber_id = fiber_id;
190
165
  }
191
166
 
192
- #ifdef RUBY_VM
193
167
  static void
194
168
  prof_event_hook(rb_event_flag_t event, VALUE data, VALUE self, ID mid, VALUE klass)
195
- #else
196
- static void
197
- prof_event_hook(rb_event_flag_t event, NODE *node, VALUE self, ID mid, VALUE klass)
198
- #endif
199
169
  {
200
- #ifndef RUBY_VM
201
- prof_profile_t* profile = pCurrentProfile;
202
- #else
203
170
  prof_profile_t* profile = prof_get_profile(data);
204
- #endif
205
-
206
171
  VALUE thread = Qnil;
207
172
  VALUE thread_id = Qnil;
208
173
  VALUE fiber = Qnil;
@@ -211,41 +176,30 @@ prof_event_hook(rb_event_flag_t event, NODE *node, VALUE self, ID mid, VALUE kla
211
176
  prof_frame_t *frame = NULL;
212
177
  double measurement;
213
178
 
214
- #ifdef RUBY_VM
215
- if (event != RUBY_EVENT_C_CALL && event != RUBY_EVENT_C_RETURN) {
179
+ if (event != RUBY_EVENT_C_CALL && event != RUBY_EVENT_C_RETURN) {
216
180
  // guess these are already set for C calls in 1.9, then?
217
181
  rb_frame_method_id_and_class(&mid, &klass);
218
- }
219
- #endif
182
+ }
220
183
 
221
184
  /* Get current measurement */
222
185
  measurement = profile->measurer->measure();
223
186
 
224
- if (trace_file != NULL)
225
- {
226
- #ifdef RUBY_VM
227
- prof_trace(profile, event, mid, klass, measurement);
228
- #else
229
- prof_trace(profile, event, node, mid, klass, measurement);
230
- #endif
231
- }
232
-
233
187
  /* Special case - skip any methods from the mProf
234
188
  module or cProfile class since they clutter
235
189
  the results but aren't important to them results. */
236
190
  if (self == mProf || klass == cProfile)
237
191
  return;
238
192
 
239
- /* Get the current thread information. */
193
+ if (trace_file != NULL)
194
+ {
195
+ prof_trace(profile, event, mid, klass, measurement);
196
+ }
197
+
198
+ /* Get the current thread and fiber information. */
240
199
  thread = rb_thread_current();
241
200
  thread_id = rb_obj_id(thread);
242
- #if defined(HAVE_RB_FIBER_CURRENT)
243
201
  fiber = rb_fiber_current();
244
202
  fiber_id = rb_obj_id(fiber);
245
- #else
246
- fiber = thread;
247
- fiber_id = thread_id;
248
- #endif
249
203
 
250
204
  if (st_lookup(profile->exclude_threads_tbl, (st_data_t) thread_id, 0))
251
205
  {
@@ -284,11 +238,7 @@ prof_event_hook(rb_event_flag_t event, NODE *node, VALUE self, ID mid, VALUE kla
284
238
  prof_call_info_t *call_info = NULL;
285
239
  prof_method_t *method = NULL;
286
240
 
287
- #ifdef RUBY_VM
288
241
  method = get_method(event, klass, mid, thread_data);
289
- #else
290
- method = get_method(event, node, klass, mid, thread_data);
291
- #endif
292
242
 
293
243
  if (!frame)
294
244
  {
@@ -334,37 +284,15 @@ prof_event_hook(rb_event_flag_t event, NODE *node, VALUE self, ID mid, VALUE kla
334
284
  void
335
285
  prof_install_hook(VALUE self)
336
286
  {
337
- #ifdef RUBY_VM
338
287
  rb_add_event_hook(prof_event_hook,
339
288
  RUBY_EVENT_CALL | RUBY_EVENT_RETURN |
340
- RUBY_EVENT_C_CALL | RUBY_EVENT_C_RETURN
341
- | RUBY_EVENT_LINE, self); // RUBY_EVENT_SWITCH
342
- #else
343
- rb_add_event_hook(prof_event_hook,
344
- RUBY_EVENT_CALL | RUBY_EVENT_RETURN |
345
- RUBY_EVENT_C_CALL | RUBY_EVENT_C_RETURN
346
- | RUBY_EVENT_LINE);
347
-
348
- pCurrentProfile = prof_get_profile(self);
349
- #endif
350
-
351
- #if defined(TOGGLE_GC_STATS)
352
- rb_gc_enable_stats();
353
- #endif
289
+ RUBY_EVENT_C_CALL | RUBY_EVENT_C_RETURN |
290
+ RUBY_EVENT_LINE, self);
354
291
  }
355
292
 
356
293
  void
357
294
  prof_remove_hook()
358
295
  {
359
- #if defined(TOGGLE_GC_STATS)
360
- rb_gc_disable_stats();
361
- #endif
362
-
363
- #ifndef RUBY_VM
364
- pCurrentProfile = NULL;
365
- #endif
366
-
367
- /* Now unregister from event */
368
296
  rb_remove_event_hook(prof_event_hook);
369
297
  }
370
298
 
@@ -508,19 +436,12 @@ prof_start(VALUE self)
508
436
  char* trace_file_name;
509
437
 
510
438
  prof_profile_t* profile = prof_get_profile(self);
511
-
439
+
512
440
  if (profile->running == Qtrue)
513
441
  {
514
442
  rb_raise(rb_eRuntimeError, "RubyProf.start was already called");
515
443
  }
516
444
 
517
- #ifndef RUBY_VM
518
- if (pCurrentProfile != NULL)
519
- {
520
- rb_raise(rb_eRuntimeError, "Only one profile can run at a time on Ruby 1.8.*");
521
- }
522
- #endif
523
-
524
445
  profile->running = Qtrue;
525
446
  profile->paused = Qfalse;
526
447
  profile->last_thread_data = NULL;
@@ -674,8 +595,7 @@ prof_threads(VALUE self)
674
595
  void Init_ruby_prof()
675
596
  {
676
597
  mProf = rb_define_module("RubyProf");
677
- rb_define_const(mProf, "VERSION", rb_str_new2(RUBY_PROF_VERSION));
678
-
598
+
679
599
  rp_init_measure();
680
600
  rp_init_method_info();
681
601
  rp_init_call_info();