ruby-prof 1.5.0 → 1.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +13 -0
  3. data/ext/ruby_prof/rp_allocation.c +136 -81
  4. data/ext/ruby_prof/rp_allocation.h +8 -6
  5. data/ext/ruby_prof/rp_call_tree.c +8 -1
  6. data/ext/ruby_prof/rp_measurement.c +10 -3
  7. data/ext/ruby_prof/rp_method.c +51 -76
  8. data/ext/ruby_prof/rp_profile.c +62 -77
  9. data/ext/ruby_prof/rp_profile.h +1 -0
  10. data/ext/ruby_prof/rp_thread.c +14 -4
  11. data/ext/ruby_prof/vc/ruby_prof.vcxproj +1 -1
  12. data/lib/ruby-prof/compatibility.rb +14 -0
  13. data/lib/ruby-prof/printers/abstract_printer.rb +1 -1
  14. data/lib/ruby-prof/printers/call_tree_printer.rb +1 -1
  15. data/lib/ruby-prof/printers/multi_printer.rb +17 -17
  16. data/lib/ruby-prof/profile.rb +5 -5
  17. data/lib/ruby-prof/rack.rb +31 -21
  18. data/lib/ruby-prof/version.rb +1 -1
  19. data/test/abstract_printer_test.rb +1 -0
  20. data/test/alias_test.rb +6 -11
  21. data/test/call_tree_visitor_test.rb +1 -6
  22. data/test/call_trees_test.rb +2 -2
  23. data/test/{basic_test.rb → compatibility_test.rb} +8 -2
  24. data/test/duplicate_names_test.rb +1 -1
  25. data/test/dynamic_method_test.rb +1 -6
  26. data/test/enumerable_test.rb +1 -1
  27. data/test/exceptions_test.rb +2 -2
  28. data/test/exclude_methods_test.rb +3 -8
  29. data/test/exclude_threads_test.rb +4 -9
  30. data/test/fiber_test.rb +4 -9
  31. data/test/gc_test.rb +2 -1
  32. data/test/inverse_call_tree_test.rb +33 -34
  33. data/test/line_number_test.rb +1 -1
  34. data/test/marshal_test.rb +3 -3
  35. data/test/measure_allocations_test.rb +8 -17
  36. data/test/measure_memory_test.rb +3 -12
  37. data/test/measure_process_time_test.rb +29 -34
  38. data/test/measure_wall_time_test.rb +176 -181
  39. data/test/multi_printer_test.rb +0 -5
  40. data/test/no_method_class_test.rb +1 -1
  41. data/test/pause_resume_test.rb +12 -16
  42. data/test/printer_call_stack_test.rb +2 -2
  43. data/test/printer_call_tree_test.rb +2 -2
  44. data/test/printer_flat_test.rb +1 -1
  45. data/test/printer_graph_html_test.rb +2 -2
  46. data/test/printer_graph_test.rb +2 -2
  47. data/test/printers_test.rb +14 -20
  48. data/test/printing_recursive_graph_test.rb +2 -2
  49. data/test/recursive_test.rb +2 -7
  50. data/test/singleton_test.rb +1 -1
  51. data/test/stack_printer_test.rb +5 -8
  52. data/test/start_stop_test.rb +11 -14
  53. data/test/thread_test.rb +13 -15
  54. data/test/unique_call_path_test.rb +4 -4
  55. data/test/yarv_test.rb +3 -3
  56. metadata +4 -4
@@ -103,17 +103,15 @@ static int excludes_method(st_data_t key, prof_profile_t* profile)
103
103
  method_table_lookup(profile->exclude_methods_tbl, key) != NULL);
104
104
  }
105
105
 
106
- static prof_method_t* create_method(VALUE profile, st_data_t key, VALUE klass, VALUE msym, VALUE source_file, int source_line)
106
+ static prof_method_t* create_method(prof_profile_t* profile, st_data_t key, VALUE klass, VALUE msym, VALUE source_file, int source_line)
107
107
  {
108
- prof_method_t* result = prof_method_create(profile, klass, msym, source_file, source_line);
109
-
110
- prof_profile_t* profile_t = prof_get_profile(profile);
111
- method_table_insert(profile_t->last_thread_data->method_table, result->key, result);
108
+ prof_method_t* result = prof_method_create(profile->object, klass, msym, source_file, source_line);
109
+ method_table_insert(profile->last_thread_data->method_table, result->key, result);
112
110
 
113
111
  return result;
114
112
  }
115
113
 
116
- static prof_method_t* check_parent_method(VALUE profile, thread_data_t* thread_data)
114
+ static prof_method_t* check_parent_method(prof_profile_t* profile, thread_data_t* thread_data)
117
115
  {
118
116
  VALUE msym = ID2SYM(rb_intern("_inserted_parent_"));
119
117
  st_data_t key = method_key(cProfile, msym);
@@ -128,7 +126,7 @@ static prof_method_t* check_parent_method(VALUE profile, thread_data_t* thread_d
128
126
  return result;
129
127
  }
130
128
 
131
- prof_method_t* check_method(VALUE profile, rb_trace_arg_t* trace_arg, rb_event_flag_t event, thread_data_t* thread_data)
129
+ prof_method_t* check_method(prof_profile_t* profile, rb_trace_arg_t* trace_arg, rb_event_flag_t event, thread_data_t* thread_data)
132
130
  {
133
131
  VALUE klass = rb_tracearg_defined_class(trace_arg);
134
132
 
@@ -142,8 +140,7 @@ prof_method_t* check_method(VALUE profile, rb_trace_arg_t* trace_arg, rb_event_f
142
140
 
143
141
  st_data_t key = method_key(klass, msym);
144
142
 
145
- prof_profile_t* profile_t = prof_get_profile(profile);
146
- if (excludes_method(key, profile_t))
143
+ if (excludes_method(key, profile))
147
144
  return NULL;
148
145
 
149
146
  prof_method_t* result = method_table_lookup(thread_data->method_table, key);
@@ -197,17 +194,16 @@ static void prof_trace(prof_profile_t* profile, rb_trace_arg_t* trace_arg, doubl
197
194
 
198
195
  static void prof_event_hook(VALUE trace_point, void* data)
199
196
  {
200
- VALUE profile = (VALUE)data;
201
- prof_profile_t* profile_t = prof_get_profile(profile);
197
+ prof_profile_t* profile = (prof_profile_t*)(data);
202
198
 
203
199
  rb_trace_arg_t* trace_arg = rb_tracearg_from_tracepoint(trace_point);
204
- double measurement = prof_measure(profile_t->measurer, trace_arg);
200
+ double measurement = prof_measure(profile->measurer, trace_arg);
205
201
  rb_event_flag_t event = rb_tracearg_event_flag(trace_arg);
206
202
  VALUE self = rb_tracearg_self(trace_arg);
207
203
 
208
204
  if (trace_file != NULL)
209
205
  {
210
- prof_trace(profile_t, trace_arg, measurement);
206
+ prof_trace(profile, trace_arg, measurement);
211
207
  }
212
208
 
213
209
  /* Special case - skip any methods from the mProf
@@ -215,7 +211,7 @@ static void prof_event_hook(VALUE trace_point, void* data)
215
211
  if (self == mProf)
216
212
  return;
217
213
 
218
- thread_data_t* thread_data = check_fiber(profile_t, measurement);
214
+ thread_data_t* thread_data = check_fiber(profile, measurement);
219
215
 
220
216
  if (!thread_data->trace)
221
217
  return;
@@ -247,7 +243,7 @@ static void prof_event_hook(VALUE trace_point, void* data)
247
243
  // This is the first method to be profiled
248
244
  else
249
245
  {
250
- frame = prof_frame_push(thread_data->stack, call_tree, measurement, RTEST(profile_t->paused));
246
+ frame = prof_frame_push(thread_data->stack, call_tree, measurement, RTEST(profile->paused));
251
247
  }
252
248
 
253
249
  thread_data->call_tree = call_tree;
@@ -301,7 +297,7 @@ static void prof_event_hook(VALUE trace_point, void* data)
301
297
  thread_data->call_tree = call_tree;
302
298
 
303
299
  // Push a new frame onto the stack for a new c-call or ruby call (into a method)
304
- prof_frame_t* next_frame = prof_frame_push(thread_data->stack, call_tree, measurement, RTEST(profile_t->paused));
300
+ prof_frame_t* next_frame = prof_frame_push(thread_data->stack, call_tree, measurement, RTEST(profile->paused));
305
301
  next_frame->source_file = method->source_file;
306
302
  next_frame->source_line = method->source_line;
307
303
  break;
@@ -327,7 +323,7 @@ static void prof_event_hook(VALUE trace_point, void* data)
327
323
 
328
324
  prof_method_t* method = prof_find_method(thread_data->stack, source_file, source_line);
329
325
  if (method)
330
- prof_allocate_increment(method, trace_arg);
326
+ prof_allocate_increment(method->allocations_table, trace_arg);
331
327
 
332
328
  break;
333
329
  }
@@ -342,12 +338,12 @@ void prof_install_hook(VALUE self)
342
338
  RUBY_EVENT_CALL | RUBY_EVENT_RETURN |
343
339
  RUBY_EVENT_C_CALL | RUBY_EVENT_C_RETURN |
344
340
  RUBY_EVENT_LINE,
345
- prof_event_hook, (void*)self);
341
+ prof_event_hook, profile);
346
342
  rb_ary_push(profile->tracepoints, event_tracepoint);
347
343
 
348
344
  if (profile->measurer->track_allocations)
349
345
  {
350
- VALUE allocation_tracepoint = rb_tracepoint_new(Qnil, RUBY_INTERNAL_EVENT_NEWOBJ, prof_event_hook, (void*)self);
346
+ VALUE allocation_tracepoint = rb_tracepoint_new(Qnil, RUBY_INTERNAL_EVENT_NEWOBJ, prof_event_hook, profile);
351
347
  rb_ary_push(profile->tracepoints, allocation_tracepoint);
352
348
  }
353
349
 
@@ -404,9 +400,10 @@ static int prof_profile_mark_methods(st_data_t key, st_data_t value, st_data_t r
404
400
  static void prof_profile_mark(void* data)
405
401
  {
406
402
  prof_profile_t* profile = (prof_profile_t*)data;
407
- rb_gc_mark(profile->tracepoints);
408
- rb_gc_mark(profile->running);
409
- rb_gc_mark(profile->paused);
403
+ rb_gc_mark_movable(profile->object);
404
+ rb_gc_mark_movable(profile->tracepoints);
405
+ rb_gc_mark_movable(profile->running);
406
+ rb_gc_mark_movable(profile->paused);
410
407
 
411
408
  // If GC stress is true (useful for debugging), when threads_table_create is called in the
412
409
  // allocate method Ruby will immediately call this mark method. Thus the threads_tbl will be NULL.
@@ -417,6 +414,15 @@ static void prof_profile_mark(void* data)
417
414
  rb_st_foreach(profile->exclude_methods_tbl, prof_profile_mark_methods, 0);
418
415
  }
419
416
 
417
+ void prof_profile_compact(void* data)
418
+ {
419
+ prof_profile_t* profile = (prof_profile_t*)data;
420
+ profile->object = rb_gc_location(profile->object);
421
+ profile->tracepoints = rb_gc_location(profile->tracepoints);
422
+ profile->running = rb_gc_location(profile->running);
423
+ profile->paused = rb_gc_location(profile->paused);
424
+ }
425
+
420
426
  /* Freeing the profile creates a cascade of freeing. It frees its threads table, which frees
421
427
  each thread and its associated call treee and methods. */
422
428
  static void prof_profile_ruby_gc_free(void* data)
@@ -462,6 +468,7 @@ static const rb_data_type_t profile_type =
462
468
  .dmark = prof_profile_mark,
463
469
  .dfree = prof_profile_ruby_gc_free,
464
470
  .dsize = prof_profile_size,
471
+ .dcompact = prof_profile_compact
465
472
  },
466
473
  .data = NULL,
467
474
  .flags = RUBY_TYPED_FREE_IMMEDIATELY
@@ -472,6 +479,7 @@ static VALUE prof_allocate(VALUE klass)
472
479
  VALUE result;
473
480
  prof_profile_t* profile;
474
481
  result = TypedData_Make_Struct(klass, prof_profile_t, &profile_type, profile);
482
+ profile->object = result;
475
483
  profile->threads_tbl = threads_table_create();
476
484
  profile->exclude_threads_tbl = NULL;
477
485
  profile->include_threads_tbl = NULL;
@@ -510,9 +518,9 @@ prof_stop_threads(prof_profile_t* profile)
510
518
 
511
519
  /* call-seq:
512
520
  new()
513
- new(options)
521
+ new(keyword_args)
514
522
 
515
- Returns a new profiler. Possible options for the options hash are:
523
+ Returns a new profiler. Possible keyword arguments include:
516
524
 
517
525
  measure_mode: Measure mode. Specifies the profile measure mode.
518
526
  If not specified, defaults to RubyProf::WALL_TIME.
@@ -525,78 +533,55 @@ prof_stop_threads(prof_profile_t* profile)
525
533
  all other threads. */
526
534
  static VALUE prof_initialize(int argc, VALUE* argv, VALUE self)
527
535
  {
536
+ VALUE keywords;
537
+ rb_scan_args_kw(RB_SCAN_ARGS_KEYWORDS, argc, argv, ":", &keywords);
538
+
539
+ ID table[] = {rb_intern("measure_mode"),
540
+ rb_intern("track_allocations"),
541
+ rb_intern("allow_exceptions"),
542
+ rb_intern("exclude_common"),
543
+ rb_intern("exclude_threads"),
544
+ rb_intern("include_threads") };
545
+ VALUE values[6];
546
+ rb_get_kwargs(keywords, table, 0, 6, values);
547
+
548
+ VALUE mode = values[0] == Qundef ? INT2NUM(MEASURE_WALL_TIME) : values[0];
549
+ VALUE track_allocations = values[1] == Qtrue ? Qtrue : Qfalse;
550
+ VALUE allow_exceptions = values[2] == Qtrue ? Qtrue : Qfalse;
551
+ VALUE exclude_common = values[3] == Qtrue ? Qtrue : Qfalse;
552
+ VALUE exclude_threads = values[4];
553
+ VALUE include_threads = values[5];
554
+
555
+ Check_Type(mode, T_FIXNUM);
528
556
  prof_profile_t* profile = prof_get_profile(self);
529
- VALUE mode_or_options;
530
- VALUE mode = Qnil;
531
- VALUE exclude_threads = Qnil;
532
- VALUE include_threads = Qnil;
533
- VALUE exclude_common = Qnil;
534
- VALUE allow_exceptions = Qfalse;
535
- VALUE track_allocations = Qfalse;
536
-
537
- int i;
538
-
539
- switch (rb_scan_args(argc, argv, "02", &mode_or_options, &exclude_threads))
540
- {
541
- case 0:
542
- break;
543
- case 1:
544
- if (FIXNUM_P(mode_or_options))
545
- {
546
- mode = mode_or_options;
547
- }
548
- else
549
- {
550
- Check_Type(mode_or_options, T_HASH);
551
- mode = rb_hash_aref(mode_or_options, ID2SYM(rb_intern("measure_mode")));
552
- track_allocations = rb_hash_aref(mode_or_options, ID2SYM(rb_intern("track_allocations")));
553
- allow_exceptions = rb_hash_aref(mode_or_options, ID2SYM(rb_intern("allow_exceptions")));
554
- exclude_common = rb_hash_aref(mode_or_options, ID2SYM(rb_intern("exclude_common")));
555
- exclude_threads = rb_hash_aref(mode_or_options, ID2SYM(rb_intern("exclude_threads")));
556
- include_threads = rb_hash_aref(mode_or_options, ID2SYM(rb_intern("include_threads")));
557
- }
558
- break;
559
- case 2:
560
- Check_Type(exclude_threads, T_ARRAY);
561
- break;
562
- }
563
-
564
- if (mode == Qnil)
565
- {
566
- mode = INT2NUM(MEASURE_WALL_TIME);
567
- }
568
- else
569
- {
570
- Check_Type(mode, T_FIXNUM);
571
- }
572
- profile->measurer = prof_measurer_create(NUM2INT(mode), track_allocations == Qtrue);
573
- profile->allow_exceptions = (allow_exceptions == Qtrue);
557
+ profile->measurer = prof_measurer_create(NUM2INT(mode), RB_TEST(track_allocations));
558
+ profile->allow_exceptions = RB_TEST(allow_exceptions);
574
559
 
575
- if (exclude_threads != Qnil)
560
+ if (exclude_threads != Qundef)
576
561
  {
577
562
  Check_Type(exclude_threads, T_ARRAY);
578
563
  assert(profile->exclude_threads_tbl == NULL);
579
564
  profile->exclude_threads_tbl = threads_table_create();
580
- for (i = 0; i < RARRAY_LEN(exclude_threads); i++)
565
+ for (int i = 0; i < RARRAY_LEN(exclude_threads); i++)
581
566
  {
582
567
  VALUE thread = rb_ary_entry(exclude_threads, i);
583
568
  rb_st_insert(profile->exclude_threads_tbl, thread, Qtrue);
584
569
  }
585
570
  }
586
571
 
587
- if (include_threads != Qnil)
572
+ if (include_threads != Qundef)
588
573
  {
589
574
  Check_Type(include_threads, T_ARRAY);
590
575
  assert(profile->include_threads_tbl == NULL);
591
576
  profile->include_threads_tbl = threads_table_create();
592
- for (i = 0; i < RARRAY_LEN(include_threads); i++)
577
+ for (int i = 0; i < RARRAY_LEN(include_threads); i++)
593
578
  {
594
579
  VALUE thread = rb_ary_entry(include_threads, i);
595
580
  rb_st_insert(profile->include_threads_tbl, thread, Qtrue);
596
581
  }
597
582
  }
598
583
 
599
- if (RTEST(exclude_common))
584
+ if (RB_TEST(exclude_common))
600
585
  {
601
586
  prof_exclude_common_methods(self);
602
587
  }
@@ -820,7 +805,7 @@ static VALUE prof_remove_thread(VALUE self, VALUE thread)
820
805
  ..
821
806
  end
822
807
  */
823
- static VALUE prof_profile_object(VALUE self)
808
+ static VALUE prof_profile_instance(VALUE self)
824
809
  {
825
810
  int result;
826
811
  prof_profile_t* profile = prof_get_profile(self);
@@ -856,7 +841,7 @@ static VALUE prof_profile_object(VALUE self)
856
841
  */
857
842
  static VALUE prof_profile_class(int argc, VALUE* argv, VALUE klass)
858
843
  {
859
- return prof_profile_object(rb_class_new_instance(argc, argv, cProfile));
844
+ return prof_profile_instance(rb_class_new_instance(argc, argv, cProfile));
860
845
  }
861
846
 
862
847
  /* call-seq:
@@ -927,7 +912,7 @@ void rp_init_profile(void)
927
912
 
928
913
  rb_define_singleton_method(cProfile, "profile", prof_profile_class, -1);
929
914
  rb_define_method(cProfile, "initialize", prof_initialize, -1);
930
- rb_define_method(cProfile, "profile", prof_profile_object, 0);
915
+ rb_define_method(cProfile, "profile", prof_profile_instance, 0);
931
916
  rb_define_method(cProfile, "start", prof_start, 0);
932
917
  rb_define_method(cProfile, "stop", prof_stop, 0);
933
918
  rb_define_method(cProfile, "resume", prof_resume, 0);
@@ -12,6 +12,7 @@ extern VALUE cProfile;
12
12
 
13
13
  typedef struct prof_profile_t
14
14
  {
15
+ VALUE object;
15
16
  VALUE running;
16
17
  VALUE paused;
17
18
 
@@ -58,18 +58,18 @@ void prof_thread_mark(void* data)
58
58
  thread_data_t* thread = (thread_data_t*)data;
59
59
 
60
60
  if (thread->object != Qnil)
61
- rb_gc_mark(thread->object);
61
+ rb_gc_mark_movable(thread->object);
62
62
 
63
63
  rb_gc_mark(thread->fiber);
64
64
 
65
65
  if (thread->methods != Qnil)
66
- rb_gc_mark(thread->methods);
66
+ rb_gc_mark_movable(thread->methods);
67
67
 
68
68
  if (thread->fiber_id != Qnil)
69
- rb_gc_mark(thread->fiber_id);
69
+ rb_gc_mark_movable(thread->fiber_id);
70
70
 
71
71
  if (thread->thread_id != Qnil)
72
- rb_gc_mark(thread->thread_id);
72
+ rb_gc_mark_movable(thread->thread_id);
73
73
 
74
74
  if (thread->call_tree)
75
75
  prof_call_tree_mark(thread->call_tree);
@@ -77,6 +77,15 @@ void prof_thread_mark(void* data)
77
77
  rb_st_foreach(thread->method_table, mark_methods, 0);
78
78
  }
79
79
 
80
+ void prof_thread_compact(void* data)
81
+ {
82
+ thread_data_t* thread = (thread_data_t*)data;
83
+ thread->object = rb_gc_location(thread->object);
84
+ thread->methods = rb_gc_location(thread->methods);
85
+ thread->fiber_id = rb_gc_location(thread->fiber_id);
86
+ thread->thread_id = rb_gc_location(thread->thread_id);
87
+ }
88
+
80
89
  static void prof_thread_free(thread_data_t* thread_data)
81
90
  {
82
91
  /* Has this method object been accessed by Ruby? If
@@ -126,6 +135,7 @@ static const rb_data_type_t thread_type =
126
135
  .dmark = prof_thread_mark,
127
136
  .dfree = prof_thread_ruby_gc_free,
128
137
  .dsize = prof_thread_size,
138
+ .dcompact = prof_thread_compact
129
139
  },
130
140
  .data = NULL,
131
141
  .flags = RUBY_TYPED_FREE_IMMEDIATELY
@@ -66,7 +66,7 @@
66
66
  </PropertyGroup>
67
67
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
68
68
  <TargetExt>.so</TargetExt>
69
- <OutDir>$(SolutionDir)\..\..\..\lib\</OutDir>
69
+ <OutDir>$(SolutionDir)\..</OutDir>
70
70
  </PropertyGroup>
71
71
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
72
72
  <ClCompile>
@@ -96,4 +96,18 @@ module RubyProf
96
96
  def self.ensure_not_running!
97
97
  raise(RuntimeError, "RubyProf is already running") if running?
98
98
  end
99
+
100
+ class << self
101
+ extend Gem::Deprecate
102
+ deprecate :measure_mode, "Profile#measure_mode", 2023, 6
103
+ deprecate :measure_mode=, "Profile#measure_mode=", 2023, 6
104
+ deprecate :exclude_threads, "Profile#exclude_threads", 2023, 6
105
+ deprecate :exclude_threads=, "Profile#initialize", 2023, 6
106
+ deprecate :start, "Profile#start", 2023, 6
107
+ deprecate :pause, "Profile#pause", 2023, 6
108
+ deprecate :stop, "Profile#stop", 2023, 6
109
+ deprecate :resume, "Profile#resume", 2023, 6
110
+ deprecate :running?, "Profile#running?", 2023, 6
111
+ deprecate :profile, "Profile.profile", 2023, 6
112
+ end
99
113
  end
@@ -50,7 +50,7 @@ module RubyProf
50
50
  # options - Hash of print options. Note that each printer can
51
51
  # define its own set of options.
52
52
  #
53
- # :min_percent - Number 0 to 100 that specifes the minimum
53
+ # :min_percent - Number 0 to 100 that specifies the minimum
54
54
  # %self (the methods self time divided by the
55
55
  # overall total time) that a method must take
56
56
  # for it to be printed out in the report.
@@ -27,7 +27,7 @@ module RubyProf
27
27
 
28
28
  def determine_event_specification_and_value_scale
29
29
  @event_specification = "events: "
30
- case RubyProf.measure_mode
30
+ case @result.measure_mode
31
31
  when RubyProf::PROCESS_TIME
32
32
  @value_scale = RubyProf::CLOCKS_PER_SEC
33
33
  @event_specification << 'process_time'
@@ -6,16 +6,16 @@ module RubyProf
6
6
  # profile, a call stack profile and a graph profile.
7
7
  class MultiPrinter
8
8
  def initialize(result, printers = [:flat, :graph_html])
9
- @flat_printer = FlatPrinter.new(result) if printers.include?(:flat)
9
+ @flat_printer = printers.include?(:flat) ? FlatPrinter.new(result) : nil
10
10
 
11
- @graph_printer = GraphPrinter.new(result) if printers.include?(:graph)
12
- @graph_html_printer = GraphHtmlPrinter.new(result) if printers.include?(:graph_html)
11
+ @graph_printer = printers.include?(:graph) ? GraphPrinter.new(result) : nil
12
+ @graph_html_printer = printers.include?(:graph_html) ? GraphHtmlPrinter.new(result) : nil
13
13
 
14
- @tree_printer = CallTreePrinter.new(result) if printers.include?(:tree)
15
- @call_info_printer = CallInfoPrinter.new(result) if printers.include?(:call_tree)
14
+ @tree_printer = printers.include?(:tree) ? CallTreePrinter.new(result) : nil
15
+ @call_info_printer = printers.include?(:call_tree) ? CallInfoPrinter.new(result) : nil
16
16
 
17
- @stack_printer = CallStackPrinter.new(result) if printers.include?(:stack)
18
- @dot_printer = DotPrinter.new(result) if printers.include?(:dot)
17
+ @stack_printer = printers.include?(:stack) ? CallStackPrinter.new(result) : nil
18
+ @dot_printer = printers.include?(:dot) ? DotPrinter.new(result) : nil
19
19
  end
20
20
 
21
21
  def self.needs_dir?
@@ -28,7 +28,7 @@ module RubyProf
28
28
  def print(options)
29
29
  validate_print_params(options)
30
30
 
31
- @profile = options.delete(:profile) || "profile"
31
+ @file_name = options.delete(:profile) || "profile"
32
32
  @directory = options.delete(:path) || File.expand_path(".")
33
33
 
34
34
  print_to_flat(options) if @flat_printer
@@ -44,36 +44,36 @@ module RubyProf
44
44
 
45
45
  # the name of the flat profile file
46
46
  def flat_report
47
- "#{@directory}/#{@profile}.flat.txt"
47
+ "#{@directory}/#{@file_name}.flat.txt"
48
48
  end
49
49
 
50
50
  # the name of the graph profile file
51
51
  def graph_report
52
- "#{@directory}/#{@profile}.graph.txt"
52
+ "#{@directory}/#{@file_name}.graph.txt"
53
53
  end
54
54
 
55
55
  def graph_html_report
56
- "#{@directory}/#{@profile}.graph.html"
56
+ "#{@directory}/#{@file_name}.graph.html"
57
57
  end
58
58
 
59
59
  # the name of the callinfo profile file
60
60
  def call_info_report
61
- "#{@directory}/#{@profile}.call_tree.txt"
61
+ "#{@directory}/#{@file_name}.call_tree.txt"
62
62
  end
63
63
 
64
64
  # the name of the callgrind profile file
65
65
  def tree_report
66
- "#{@directory}/#{@profile}.callgrind.out.#{$$}"
66
+ "#{@directory}/#{@file_name}.callgrind.out.#{$$}"
67
67
  end
68
68
 
69
69
  # the name of the call stack profile file
70
70
  def stack_report
71
- "#{@directory}/#{@profile}.stack.html"
71
+ "#{@directory}/#{@file_name}.stack.html"
72
72
  end
73
73
 
74
74
  # the name of the call stack profile file
75
75
  def dot_report
76
- "#{@directory}/#{@profile}.dot"
76
+ "#{@directory}/#{@file_name}.dot"
77
77
  end
78
78
 
79
79
  def print_to_flat(options)
@@ -101,12 +101,12 @@ module RubyProf
101
101
  end
102
102
 
103
103
  def print_to_tree(options)
104
- @tree_printer.print(options.merge(:path => @directory, :profile => @profile))
104
+ @tree_printer.print(options.merge(:path => @directory, :profile => @file_name))
105
105
  end
106
106
 
107
107
  def print_to_stack(options)
108
108
  File.open(stack_report, "wb") do |file|
109
- @stack_printer.print(file, options.merge(:graph => "#{@profile}.graph.html"))
109
+ @stack_printer.print(file, options.merge(:graph => "#{@file_name}.graph.html"))
110
110
  end
111
111
  end
112
112
 
@@ -23,14 +23,14 @@ module RubyProf
23
23
  ExcludeCommonMethods.apply!(self)
24
24
  end
25
25
 
26
- def exclude_methods!(mod, *method_or_methods)
27
- [method_or_methods].flatten.each do |name|
28
- exclude_method!(mod, name)
26
+ def exclude_methods!(mod, *method_names)
27
+ [method_names].flatten.each do |method_name|
28
+ exclude_method!(mod, method_name)
29
29
  end
30
30
  end
31
31
 
32
- def exclude_singleton_methods!(mod, *method_or_methods)
33
- exclude_methods!(mod.singleton_class, *method_or_methods)
32
+ def exclude_singleton_methods!(mod, *method_names)
33
+ exclude_methods!(mod.singleton_class, *method_names)
34
34
  end
35
35
 
36
36
  # call-seq:
@@ -6,7 +6,6 @@ module Rack
6
6
  def initialize(app, options = {})
7
7
  @app = app
8
8
  @options = options
9
- @options[:min_percent] ||= 1
10
9
 
11
10
  @tmpdir = options[:path] || Dir.tmpdir
12
11
  FileUtils.mkdir_p(@tmpdir)
@@ -26,14 +25,19 @@ module Rack
26
25
  if should_profile?(request.path)
27
26
  begin
28
27
  result = nil
29
- data = ::RubyProf::Profile.profile(profiling_options) do
28
+ profile = ::RubyProf::Profile.profile(profiling_options) do
30
29
  result = @app.call(env)
31
30
  end
32
31
 
32
+ if @options[:merge_fibers]
33
+ profile.merge!
34
+ end
35
+
36
+
33
37
  path = request.path.gsub('/', '-')
34
38
  path.slice!(0)
35
39
 
36
- print(data, path)
40
+ print(profile, path)
37
41
  result
38
42
  end
39
43
  else
@@ -54,39 +58,45 @@ module Rack
54
58
  end
55
59
 
56
60
  def profiling_options
57
- options = {}
58
- options[:measure_mode] = ::RubyProf.measure_mode
59
- options[:exclude_threads] =
60
- if @options[:ignore_existing_threads]
61
- Thread.list.select{|t| t != Thread.current}
62
- else
63
- ::RubyProf.exclude_threads
64
- end
65
- if @options[:request_thread_only]
66
- options[:include_threads] = [Thread.current]
61
+ result = {}
62
+ result[:measure_mode] = @options[:measure_mode] || ::RubyProf::WALL_TIME
63
+ result[:track_allocations] = @options[:track_allocations] || false
64
+ result[:exclude_common] = @options[:exclude_common] || false
65
+
66
+ if @options[:ignore_existing_threads]
67
+ result[:exclude_threads] = Thread.list.select {|thread| thread != Thread.current}
67
68
  end
68
- if @options[:merge_fibers]
69
- options[:merge_fibers] = true
69
+
70
+ if @options[:request_thread_only]
71
+ result[:include_threads] = [Thread.current]
70
72
  end
71
- options
73
+
74
+ result
75
+ end
76
+
77
+ def print_options
78
+ result = {}
79
+ result[:min_percent] = @options[:min_percent] || 1
80
+ result[:sort_method] = @options[:sort_method] || :total_time
81
+ result
72
82
  end
73
83
 
74
- def print(data, path)
84
+ def print(profile, path)
75
85
  @printer_klasses.each do |printer_klass, base_name|
76
- printer = printer_klass.new(data)
86
+ printer = printer_klass.new(profile)
77
87
 
78
88
  if base_name.respond_to?(:call)
79
89
  base_name = base_name.call
80
90
  end
81
91
 
82
92
  if printer_klass == ::RubyProf::MultiPrinter
83
- printer.print(@options.merge(:profile => "#{path}-#{base_name}"))
93
+ printer.print(print_options.merge(:profile => "#{path}-#{base_name}"))
84
94
  elsif printer_klass == ::RubyProf::CallTreePrinter
85
- printer.print(@options.merge(:profile => "#{path}-#{base_name}"))
95
+ printer.print(print_options.merge(:profile => "#{path}-#{base_name}"))
86
96
  else
87
97
  file_name = ::File.join(@tmpdir, "#{path}-#{base_name}")
88
98
  ::File.open(file_name, 'wb') do |file|
89
- printer.print(file, @options)
99
+ printer.print(file, print_options)
90
100
  end
91
101
  end
92
102
  end
@@ -1,3 +1,3 @@
1
1
  module RubyProf
2
- VERSION = "1.5.0"
2
+ VERSION = "1.6.1"
3
3
  end
@@ -5,6 +5,7 @@ require File.expand_path('../test_helper', __FILE__)
5
5
 
6
6
  class AbstractPrinterTest < TestCase
7
7
  def setup
8
+ super
8
9
  @result = {}
9
10
  @printer = RubyProf::AbstractPrinter.new(@result)
10
11
  @options = {}