ruby-prof 1.7.2 → 2.0.1

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 (122) hide show
  1. checksums.yaml +4 -4
  2. data/{CHANGES → CHANGELOG.md} +115 -178
  3. data/README.md +5 -5
  4. data/bin/ruby-prof +1 -4
  5. data/bin/ruby-prof-check-trace +45 -45
  6. data/docs/advanced-usage.md +132 -0
  7. data/docs/alternatives.md +98 -0
  8. data/docs/architecture.md +122 -0
  9. data/docs/best-practices.md +27 -0
  10. data/docs/getting-started.md +130 -0
  11. data/docs/history.md +11 -0
  12. data/docs/index.md +45 -0
  13. data/docs/profiling-rails.md +64 -0
  14. data/docs/public/examples/example.rb +33 -0
  15. data/docs/public/examples/generate_reports.rb +92 -0
  16. data/docs/public/examples/reports/call_info.txt +27 -0
  17. data/docs/public/examples/reports/call_stack.html +835 -0
  18. data/docs/public/examples/reports/callgrind.out +150 -0
  19. data/docs/public/examples/reports/flame_graph.html +408 -0
  20. data/docs/public/examples/reports/flat.txt +45 -0
  21. data/docs/public/examples/reports/graph.dot +129 -0
  22. data/docs/public/examples/reports/graph.html +1319 -0
  23. data/docs/public/examples/reports/graph.txt +100 -0
  24. data/docs/public/examples/reports/graphviz_viewer.html +1 -0
  25. data/docs/public/images/call_stack.png +0 -0
  26. data/docs/public/images/class_diagram.png +0 -0
  27. data/docs/public/images/dot_printer.png +0 -0
  28. data/docs/public/images/flame_graph.png +0 -0
  29. data/docs/public/images/flat.png +0 -0
  30. data/docs/public/images/graph.png +0 -0
  31. data/docs/public/images/graph_html.png +0 -0
  32. data/docs/public/images/ruby-prof-logo.svg +1 -0
  33. data/docs/reports.md +150 -0
  34. data/docs/stylesheets/extra.css +80 -0
  35. data/ext/ruby_prof/rp_allocation.c +0 -15
  36. data/ext/ruby_prof/rp_allocation.h +29 -33
  37. data/ext/ruby_prof/rp_call_tree.c +3 -0
  38. data/ext/ruby_prof/rp_call_tree.h +1 -4
  39. data/ext/ruby_prof/rp_call_trees.h +1 -4
  40. data/ext/ruby_prof/rp_measurement.c +0 -5
  41. data/ext/ruby_prof/rp_measurement.h +49 -53
  42. data/ext/ruby_prof/rp_method.c +3 -0
  43. data/ext/ruby_prof/rp_method.h +1 -4
  44. data/ext/ruby_prof/rp_profile.c +1 -1
  45. data/ext/ruby_prof/rp_profile.h +1 -5
  46. data/ext/ruby_prof/rp_stack.h +50 -53
  47. data/ext/ruby_prof/rp_thread.h +1 -4
  48. data/ext/ruby_prof/ruby_prof.h +1 -4
  49. data/ext/ruby_prof/vc/ruby_prof.vcxproj +7 -8
  50. data/lib/ruby-prof/assets/call_stack_printer.html.erb +746 -711
  51. data/lib/ruby-prof/assets/flame_graph_printer.html.erb +412 -0
  52. data/lib/ruby-prof/assets/graph_printer.html.erb +355 -355
  53. data/lib/ruby-prof/call_tree.rb +57 -57
  54. data/lib/ruby-prof/call_tree_visitor.rb +36 -36
  55. data/lib/ruby-prof/measurement.rb +17 -17
  56. data/lib/ruby-prof/printers/abstract_printer.rb +19 -33
  57. data/lib/ruby-prof/printers/call_info_printer.rb +53 -53
  58. data/lib/ruby-prof/printers/call_stack_printer.rb +168 -180
  59. data/lib/ruby-prof/printers/call_tree_printer.rb +132 -145
  60. data/lib/ruby-prof/printers/dot_printer.rb +177 -132
  61. data/lib/ruby-prof/printers/flame_graph_printer.rb +79 -0
  62. data/lib/ruby-prof/printers/flat_printer.rb +52 -52
  63. data/lib/ruby-prof/printers/graph_html_printer.rb +62 -63
  64. data/lib/ruby-prof/printers/graph_printer.rb +112 -113
  65. data/lib/ruby-prof/printers/multi_printer.rb +134 -127
  66. data/lib/ruby-prof/profile.rb +13 -0
  67. data/lib/ruby-prof/rack.rb +114 -105
  68. data/lib/ruby-prof/task.rb +147 -147
  69. data/lib/ruby-prof/thread.rb +20 -20
  70. data/lib/ruby-prof/version.rb +1 -1
  71. data/lib/ruby-prof.rb +50 -52
  72. data/lib/unprof.rb +10 -10
  73. data/ruby-prof.gemspec +66 -66
  74. data/test/abstract_printer_test.rb +25 -27
  75. data/test/alias_test.rb +203 -117
  76. data/test/call_tree_builder.rb +9 -9
  77. data/test/call_tree_visitor_test.rb +27 -27
  78. data/test/call_trees_test.rb +66 -66
  79. data/test/duplicate_names_test.rb +32 -32
  80. data/test/dynamic_method_test.rb +50 -50
  81. data/test/exceptions_test.rb +1 -1
  82. data/test/exclude_threads_test.rb +48 -48
  83. data/test/fiber_test.rb +72 -72
  84. data/test/inverse_call_tree_test.rb +174 -174
  85. data/test/line_number_test.rb +138 -1
  86. data/test/marshal_test.rb +2 -3
  87. data/test/measure_allocations.rb +26 -26
  88. data/test/measure_allocations_test.rb +340 -1
  89. data/test/measure_process_time_test.rb +3098 -3142
  90. data/test/measure_times.rb +56 -56
  91. data/test/measure_wall_time_test.rb +511 -372
  92. data/test/measurement_test.rb +82 -82
  93. data/test/merge_test.rb +48 -48
  94. data/test/multi_printer_test.rb +52 -66
  95. data/test/no_method_class_test.rb +15 -15
  96. data/test/pause_resume_test.rb +171 -171
  97. data/test/prime.rb +54 -54
  98. data/test/prime_script.rb +5 -5
  99. data/test/printer_call_stack_test.rb +4 -3
  100. data/test/printer_call_tree_test.rb +30 -30
  101. data/test/printer_flame_graph_test.rb +82 -0
  102. data/test/printer_flat_test.rb +3 -3
  103. data/test/printer_graph_html_test.rb +12 -9
  104. data/test/printer_graph_test.rb +5 -3
  105. data/test/printers_test.rb +162 -178
  106. data/test/printing_recursive_graph_test.rb +4 -4
  107. data/test/profile_test.rb +2 -2
  108. data/test/rack_test.rb +15 -5
  109. data/test/recursive_test.rb +139 -139
  110. data/test/scheduler.rb +367 -363
  111. data/test/singleton_test.rb +2 -1
  112. data/test/stack_printer_test.rb +61 -61
  113. data/test/start_stop_test.rb +106 -106
  114. data/test/test_helper.rb +4 -0
  115. data/test/thread_test.rb +229 -229
  116. data/test/unique_call_path_test.rb +123 -123
  117. data/test/yarv_test.rb +2 -2
  118. metadata +53 -11
  119. data/ext/ruby_prof/rp_measure_memory.c +0 -46
  120. data/lib/ruby-prof/compatibility.rb +0 -113
  121. data/test/compatibility_test.rb +0 -49
  122. data/test/measure_memory_test.rb +0 -1193
@@ -2,6 +2,7 @@
2
2
  # encoding: UTF-8
3
3
 
4
4
  require File.expand_path('../test_helper', __FILE__)
5
+ require 'stringio'
5
6
  require 'timeout'
6
7
 
7
8
  # -- Test for bug [#5657]
@@ -32,7 +33,7 @@ class SingletonTest < TestCase
32
33
  assert_equal(1, a.as.size)
33
34
  end
34
35
  printer = RubyProf::FlatPrinter.new(result)
35
- output = ENV['SHOW_RUBY_PROF_PRINTER_OUTPUT'] == "1" ? STDOUT : ''
36
+ output = ENV['SHOW_RUBY_PROF_PRINTER_OUTPUT'] == "1" ? STDOUT : StringIO.new
36
37
  printer.print(output)
37
38
  end
38
39
  end
@@ -1,61 +1,61 @@
1
- #!/usr/bin/env ruby
2
- # encoding: UTF-8
3
-
4
- require File.expand_path('../test_helper', __FILE__)
5
-
6
- # Test data
7
- # A
8
- # / \
9
- # B C
10
- # \
11
- # B
12
-
13
- class STPT
14
- def a
15
- 100.times{b}
16
- 300.times{c}
17
- c;c;c
18
- end
19
-
20
- def b
21
- sleep 0
22
- end
23
-
24
- def c
25
- 5.times{b}
26
- end
27
- end
28
-
29
- class StackPrinterTest < TestCase
30
- def test_stack_can_be_printed
31
- start_time = Time.now
32
- result = RubyProf::Profile.profile(measure_mode: RubyProf::WALL_TIME) do
33
- 5.times{STPT.new.a}
34
- end
35
-
36
- end_time = Time.now
37
- expected_time = end_time - start_time
38
-
39
- file_contents = nil
40
- file_contents = print(result)
41
- re = /Thread: (\d+)(, Fiber: (\d+))? \([\.0-9]+.[\.0-9]+% ~ ([\.0-9]+)\)/
42
- assert_match(re, file_contents)
43
- file_contents =~ re
44
- actual_time = $4.to_f
45
- assert_in_delta(expected_time, actual_time, 0.1)
46
- end
47
-
48
- private
49
-
50
- def print(result)
51
- test = caller.first =~ /in `(.*)'/ ? $1 : "test"
52
- testfile_name = "#{Dir.tmpdir}/ruby_prof_#{test}.html"
53
- # puts "printing to #{testfile_name}"
54
- printer = RubyProf::CallStackPrinter.new(result)
55
- File.open(testfile_name, "w") {|f| printer.print(f, :threshold => 0, :min_percent => 0, :title => "ruby_prof #{test}")}
56
- system("open '#{testfile_name}'") if RUBY_PLATFORM =~ /darwin/ && ENV['SHOW_RUBY_PROF_PRINTER_OUTPUT']=="1"
57
- assert File.exist?(testfile_name), "#{testfile_name} does not exist"
58
- assert File.readable?(testfile_name), "#{testfile_name} is no readable"
59
- File.read(testfile_name)
60
- end
61
- end
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+
6
+ # Test data
7
+ # A
8
+ # / \
9
+ # B C
10
+ # \
11
+ # B
12
+
13
+ class STPT
14
+ def a
15
+ 100.times{b}
16
+ 300.times{c}
17
+ c;c;c
18
+ end
19
+
20
+ def b
21
+ sleep 0
22
+ end
23
+
24
+ def c
25
+ 5.times{b}
26
+ end
27
+ end
28
+
29
+ class StackPrinterTest < TestCase
30
+ def test_stack_can_be_printed
31
+ start_time = Time.now
32
+ result = RubyProf::Profile.profile(measure_mode: RubyProf::WALL_TIME) do
33
+ 5.times{STPT.new.a}
34
+ end
35
+
36
+ end_time = Time.now
37
+ expected_time = end_time - start_time
38
+
39
+ file_contents = nil
40
+ file_contents = print(result)
41
+ re = /Thread: (\d+)(, Fiber: (\d+))? \([\.0-9]+.[\.0-9]+% ~ ([\.0-9]+)\)/
42
+ assert_match(re, file_contents)
43
+ file_contents =~ re
44
+ actual_time = $4.to_f
45
+ assert_in_delta(expected_time, actual_time, 0.1)
46
+ end
47
+
48
+ private
49
+
50
+ def print(result)
51
+ test = caller.first =~ /in `(.*)'/ ? $1 : "test"
52
+ testfile_name = "#{Dir.tmpdir}/ruby_prof_#{test}.html"
53
+ # puts "printing to #{testfile_name}"
54
+ printer = RubyProf::CallStackPrinter.new(result)
55
+ File.open(testfile_name, "w") {|f| printer.print(f, threshold: 0, min_percent: 0, title: "ruby_prof #{test}")}
56
+ system("open '#{testfile_name}'") if RUBY_PLATFORM =~ /darwin/ && ENV['SHOW_RUBY_PROF_PRINTER_OUTPUT']=="1"
57
+ assert File.exist?(testfile_name), "#{testfile_name} does not exist"
58
+ assert File.readable?(testfile_name), "#{testfile_name} is no readable"
59
+ File.read(testfile_name)
60
+ end
61
+ end
@@ -1,106 +1,106 @@
1
- #!/usr/bin/env ruby
2
- # encoding: UTF-8
3
-
4
- require File.expand_path('../test_helper', __FILE__)
5
-
6
- class StartStopTest < TestCase
7
- def setup
8
- super
9
- # Need to use wall time for this test due to the sleep calls
10
- @profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
11
- end
12
-
13
- def method1
14
- @profile.start
15
- method2
16
- end
17
-
18
- def method2
19
- method3
20
- end
21
-
22
- def method3
23
- sleep(2)
24
- @result = @profile.stop
25
- end
26
-
27
- def test_extra_stop_should_raise
28
- @profile.start
29
- assert_raises(RuntimeError) do
30
- @profile.start
31
- end
32
-
33
- @profile.stop # ok
34
- assert_raises(RuntimeError) do
35
- @profile.stop
36
- end
37
- end
38
-
39
- def test_different_methods
40
- method1
41
-
42
- # Ruby prof should be stopped
43
- assert_equal(false, @profile.running?)
44
-
45
- methods = @result.threads.first.methods.sort.reverse
46
- assert_equal(4, methods.length)
47
-
48
- method = methods[0]
49
- assert_equal('StartStopTest#method1', method.full_name)
50
- assert_equal(1, method.called)
51
- assert_in_delta(2, method.total_time, 0.05)
52
- assert_in_delta(0, method.wait_time, 0.02)
53
- assert_in_delta(0, method.self_time, 0.02)
54
- assert_in_delta(2, method.children_time, 0.05)
55
-
56
- assert_equal(1, method.call_trees.callees.length)
57
- call_tree = method.call_trees.callees[0]
58
- assert_equal('StartStopTest#method2', call_tree.target.full_name)
59
-
60
- method = methods[1]
61
- assert_equal('StartStopTest#method2', method.full_name)
62
- assert_equal(1, method.called)
63
- assert_in_delta(2, method.total_time, 0.05)
64
- assert_in_delta(0, method.wait_time, 0.02)
65
- assert_in_delta(0, method.self_time, 0.02)
66
- assert_in_delta(2, method.children_time, 0.05)
67
-
68
- assert_equal(1, method.call_trees.callers.length)
69
- call_tree = method.call_trees.callers[0]
70
- assert_equal('StartStopTest#method1', call_tree.parent.target.full_name)
71
-
72
- assert_equal(1, method.call_trees.callees.length)
73
- call_tree = method.call_trees.callees[0]
74
- assert_equal('StartStopTest#method3', call_tree.target.full_name)
75
-
76
- method = methods[2]
77
- assert_equal('StartStopTest#method3', method.full_name)
78
- assert_equal(1, method.called)
79
- assert_in_delta(2, method.total_time, 0.05)
80
- assert_in_delta(0, method.wait_time, 0.02)
81
- assert_in_delta(0, method.self_time, 0.02)
82
- assert_in_delta(2, method.children_time, 0.05)
83
-
84
- assert_equal(1, method.call_trees.callers.length)
85
- call_tree = method.call_trees.callers[0]
86
- assert_equal('StartStopTest#method2', call_tree.parent.target.full_name)
87
-
88
- assert_equal(1, method.call_trees.callees.length)
89
- call_tree = method.call_trees.callees[0]
90
- assert_equal('Kernel#sleep', call_tree.target.full_name)
91
-
92
- method = methods[3]
93
- assert_equal('Kernel#sleep', method.full_name)
94
- assert_equal(1, method.called)
95
- assert_in_delta(2, method.total_time, 0.05)
96
- assert_in_delta(0, method.wait_time, 0.02)
97
- assert_in_delta(2, method.self_time, 0.02)
98
- assert_in_delta(0, method.children_time, 0.05)
99
-
100
- assert_equal(1, method.call_trees.callers.length)
101
- call_tree = method.call_trees.callers[0]
102
- assert_equal('StartStopTest#method3', call_tree.parent.target.full_name)
103
-
104
- assert_equal(0, method.call_trees.callees.length)
105
- end
106
- end
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+
6
+ class StartStopTest < TestCase
7
+ def setup
8
+ super
9
+ # Need to use wall time for this test due to the sleep calls
10
+ @profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
11
+ end
12
+
13
+ def method1
14
+ @profile.start
15
+ method2
16
+ end
17
+
18
+ def method2
19
+ method3
20
+ end
21
+
22
+ def method3
23
+ sleep(2)
24
+ @result = @profile.stop
25
+ end
26
+
27
+ def test_extra_stop_should_raise
28
+ @profile.start
29
+ assert_raises(RuntimeError) do
30
+ @profile.start
31
+ end
32
+
33
+ @profile.stop # ok
34
+ assert_raises(RuntimeError) do
35
+ @profile.stop
36
+ end
37
+ end
38
+
39
+ def test_different_methods
40
+ method1
41
+
42
+ # Ruby prof should be stopped
43
+ assert_equal(false, @profile.running?)
44
+
45
+ methods = @result.threads.first.methods.sort.reverse
46
+ assert_equal(4, methods.length)
47
+
48
+ method = methods[0]
49
+ assert_equal('StartStopTest#method1', method.full_name)
50
+ assert_equal(1, method.called)
51
+ assert_in_delta(2, method.total_time, 0.05 * delta_multiplier)
52
+ assert_in_delta(0, method.wait_time, 0.02 * delta_multiplier)
53
+ assert_in_delta(0, method.self_time, 0.02 * delta_multiplier)
54
+ assert_in_delta(2, method.children_time, 0.05 * delta_multiplier)
55
+
56
+ assert_equal(1, method.call_trees.callees.length)
57
+ call_tree = method.call_trees.callees[0]
58
+ assert_equal('StartStopTest#method2', call_tree.target.full_name)
59
+
60
+ method = methods[1]
61
+ assert_equal('StartStopTest#method2', method.full_name)
62
+ assert_equal(1, method.called)
63
+ assert_in_delta(2, method.total_time, 0.05 * delta_multiplier)
64
+ assert_in_delta(0, method.wait_time, 0.02 * delta_multiplier)
65
+ assert_in_delta(0, method.self_time, 0.02 * delta_multiplier)
66
+ assert_in_delta(2, method.children_time, 0.05 * delta_multiplier)
67
+
68
+ assert_equal(1, method.call_trees.callers.length)
69
+ call_tree = method.call_trees.callers[0]
70
+ assert_equal('StartStopTest#method1', call_tree.parent.target.full_name)
71
+
72
+ assert_equal(1, method.call_trees.callees.length)
73
+ call_tree = method.call_trees.callees[0]
74
+ assert_equal('StartStopTest#method3', call_tree.target.full_name)
75
+
76
+ method = methods[2]
77
+ assert_equal('StartStopTest#method3', method.full_name)
78
+ assert_equal(1, method.called)
79
+ assert_in_delta(2, method.total_time, 0.05 * delta_multiplier)
80
+ assert_in_delta(0, method.wait_time, 0.02 * delta_multiplier)
81
+ assert_in_delta(0, method.self_time, 0.02 * delta_multiplier)
82
+ assert_in_delta(2, method.children_time, 0.05 * delta_multiplier)
83
+
84
+ assert_equal(1, method.call_trees.callers.length)
85
+ call_tree = method.call_trees.callers[0]
86
+ assert_equal('StartStopTest#method2', call_tree.parent.target.full_name)
87
+
88
+ assert_equal(1, method.call_trees.callees.length)
89
+ call_tree = method.call_trees.callees[0]
90
+ assert_equal('Kernel#sleep', call_tree.target.full_name)
91
+
92
+ method = methods[3]
93
+ assert_equal('Kernel#sleep', method.full_name)
94
+ assert_equal(1, method.called)
95
+ assert_in_delta(2, method.total_time, 0.05 * delta_multiplier)
96
+ assert_in_delta(0, method.wait_time, 0.02 * delta_multiplier)
97
+ assert_in_delta(2, method.self_time, 0.05 * delta_multiplier)
98
+ assert_in_delta(0, method.children_time, 0.02 * delta_multiplier)
99
+
100
+ assert_equal(1, method.call_trees.callers.length)
101
+ call_tree = method.call_trees.callers[0]
102
+ assert_equal('StartStopTest#method3', call_tree.parent.target.full_name)
103
+
104
+ assert_equal(0, method.call_trees.callees.length)
105
+ end
106
+ end
data/test/test_helper.rb CHANGED
@@ -16,5 +16,9 @@ ENV["MT_CPU"] = "0" # New versions of minitest
16
16
  ENV["N"] = "0" # Older versions of minitest
17
17
 
18
18
  require 'minitest/autorun'
19
+ Minitest.load_plugins
19
20
  class TestCase < Minitest::Test
21
+ def delta_multiplier
22
+ osx? && ENV["GITHUB_ACTIONS"] ? 6 : 1
23
+ end
20
24
  end