ruby-prof 1.7.2 → 2.0.0

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 (121) hide show
  1. checksums.yaml +4 -4
  2. data/{CHANGES → CHANGELOG.md} +112 -178
  3. data/README.md +5 -5
  4. data/bin/ruby-prof +1 -4
  5. data/docs/advanced-usage.md +132 -0
  6. data/docs/alternatives.md +98 -0
  7. data/docs/architecture.md +122 -0
  8. data/docs/best-practices.md +27 -0
  9. data/docs/getting-started.md +130 -0
  10. data/docs/history.md +11 -0
  11. data/docs/index.md +45 -0
  12. data/docs/profiling-rails.md +64 -0
  13. data/docs/public/examples/example.rb +33 -0
  14. data/docs/public/examples/generate_reports.rb +92 -0
  15. data/docs/public/examples/reports/call_info.txt +27 -0
  16. data/docs/public/examples/reports/call_stack.html +835 -0
  17. data/docs/public/examples/reports/callgrind.out +150 -0
  18. data/docs/public/examples/reports/flame_graph.html +408 -0
  19. data/docs/public/examples/reports/flat.txt +45 -0
  20. data/docs/public/examples/reports/graph.dot +129 -0
  21. data/docs/public/examples/reports/graph.html +1319 -0
  22. data/docs/public/examples/reports/graph.txt +100 -0
  23. data/docs/public/examples/reports/graphviz_viewer.html +1 -0
  24. data/docs/public/images/call_stack.png +0 -0
  25. data/docs/public/images/class_diagram.png +0 -0
  26. data/docs/public/images/dot_printer.png +0 -0
  27. data/docs/public/images/flame_graph.png +0 -0
  28. data/docs/public/images/flat.png +0 -0
  29. data/docs/public/images/graph.png +0 -0
  30. data/docs/public/images/graph_html.png +0 -0
  31. data/docs/public/images/ruby-prof-logo.svg +1 -0
  32. data/docs/reports.md +150 -0
  33. data/docs/stylesheets/extra.css +80 -0
  34. data/ext/ruby_prof/rp_allocation.c +0 -15
  35. data/ext/ruby_prof/rp_allocation.h +29 -33
  36. data/ext/ruby_prof/rp_call_tree.c +3 -0
  37. data/ext/ruby_prof/rp_call_tree.h +1 -4
  38. data/ext/ruby_prof/rp_call_trees.h +1 -4
  39. data/ext/ruby_prof/rp_measurement.c +0 -5
  40. data/ext/ruby_prof/rp_measurement.h +49 -53
  41. data/ext/ruby_prof/rp_method.c +3 -0
  42. data/ext/ruby_prof/rp_method.h +1 -4
  43. data/ext/ruby_prof/rp_profile.c +1 -1
  44. data/ext/ruby_prof/rp_profile.h +1 -5
  45. data/ext/ruby_prof/rp_stack.h +50 -53
  46. data/ext/ruby_prof/rp_thread.h +1 -4
  47. data/ext/ruby_prof/ruby_prof.h +1 -4
  48. data/ext/ruby_prof/vc/ruby_prof.vcxproj +7 -8
  49. data/lib/ruby-prof/assets/call_stack_printer.html.erb +746 -711
  50. data/lib/ruby-prof/assets/flame_graph_printer.html.erb +412 -0
  51. data/lib/ruby-prof/assets/graph_printer.html.erb +355 -355
  52. data/lib/ruby-prof/call_tree.rb +57 -57
  53. data/lib/ruby-prof/call_tree_visitor.rb +36 -36
  54. data/lib/ruby-prof/measurement.rb +17 -17
  55. data/lib/ruby-prof/printers/abstract_printer.rb +19 -33
  56. data/lib/ruby-prof/printers/call_info_printer.rb +53 -53
  57. data/lib/ruby-prof/printers/call_stack_printer.rb +168 -180
  58. data/lib/ruby-prof/printers/call_tree_printer.rb +132 -145
  59. data/lib/ruby-prof/printers/dot_printer.rb +177 -132
  60. data/lib/ruby-prof/printers/flame_graph_printer.rb +79 -0
  61. data/lib/ruby-prof/printers/flat_printer.rb +52 -52
  62. data/lib/ruby-prof/printers/graph_html_printer.rb +62 -63
  63. data/lib/ruby-prof/printers/graph_printer.rb +112 -113
  64. data/lib/ruby-prof/printers/multi_printer.rb +134 -127
  65. data/lib/ruby-prof/profile.rb +13 -0
  66. data/lib/ruby-prof/rack.rb +114 -105
  67. data/lib/ruby-prof/task.rb +147 -147
  68. data/lib/ruby-prof/thread.rb +20 -20
  69. data/lib/ruby-prof/version.rb +1 -1
  70. data/lib/ruby-prof.rb +50 -52
  71. data/lib/unprof.rb +10 -10
  72. data/ruby-prof.gemspec +5 -5
  73. data/test/abstract_printer_test.rb +25 -27
  74. data/test/alias_test.rb +203 -117
  75. data/test/call_tree_builder.rb +126 -126
  76. data/test/call_tree_visitor_test.rb +27 -27
  77. data/test/call_trees_test.rb +66 -66
  78. data/test/duplicate_names_test.rb +32 -32
  79. data/test/dynamic_method_test.rb +50 -50
  80. data/test/exceptions_test.rb +24 -24
  81. data/test/exclude_threads_test.rb +48 -48
  82. data/test/fiber_test.rb +72 -72
  83. data/test/inverse_call_tree_test.rb +174 -174
  84. data/test/line_number_test.rb +138 -1
  85. data/test/marshal_test.rb +144 -145
  86. data/test/measure_allocations.rb +26 -26
  87. data/test/measure_allocations_test.rb +340 -1
  88. data/test/measure_process_time_test.rb +3098 -3142
  89. data/test/measure_times.rb +56 -56
  90. data/test/measure_wall_time_test.rb +511 -372
  91. data/test/measurement_test.rb +82 -82
  92. data/test/merge_test.rb +48 -48
  93. data/test/multi_printer_test.rb +52 -66
  94. data/test/no_method_class_test.rb +15 -15
  95. data/test/pause_resume_test.rb +171 -171
  96. data/test/prime.rb +54 -54
  97. data/test/prime_script.rb +5 -5
  98. data/test/printer_call_stack_test.rb +28 -27
  99. data/test/printer_call_tree_test.rb +30 -30
  100. data/test/printer_flame_graph_test.rb +82 -0
  101. data/test/printer_flat_test.rb +99 -99
  102. data/test/printer_graph_html_test.rb +62 -59
  103. data/test/printer_graph_test.rb +42 -40
  104. data/test/printers_test.rb +28 -44
  105. data/test/printing_recursive_graph_test.rb +81 -81
  106. data/test/profile_test.rb +101 -101
  107. data/test/rack_test.rb +103 -93
  108. data/test/recursive_test.rb +139 -139
  109. data/test/scheduler.rb +4 -0
  110. data/test/singleton_test.rb +39 -38
  111. data/test/stack_printer_test.rb +61 -61
  112. data/test/start_stop_test.rb +106 -106
  113. data/test/test_helper.rb +4 -0
  114. data/test/thread_test.rb +29 -29
  115. data/test/unique_call_path_test.rb +123 -123
  116. data/test/yarv_test.rb +56 -56
  117. metadata +53 -11
  118. data/ext/ruby_prof/rp_measure_memory.c +0 -46
  119. data/lib/ruby-prof/compatibility.rb +0 -113
  120. data/test/compatibility_test.rb +0 -49
  121. data/test/measure_memory_test.rb +0 -1193
@@ -1,171 +1,171 @@
1
- #!/usr/bin/env ruby
2
- # encoding: UTF-8
3
-
4
- require File.expand_path('../test_helper', __FILE__)
5
- require_relative 'measure_times'
6
-
7
- class PauseResumeTest < TestCase
8
- def test_pause_resume
9
- profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
10
- # Measured
11
- profile.start
12
- RubyProf::C1.sleep_wait
13
-
14
- # Not measured
15
- profile.pause
16
- sleep 1
17
- RubyProf::C1.sleep_wait
18
-
19
- # Measured
20
- profile.resume
21
- RubyProf::C1.sleep_wait
22
-
23
- result = profile.stop
24
-
25
- # Length should be 3:
26
- # PauseResumeTest#test_pause_resume
27
- # <Class::RubyProf::C1>#sleep_wait
28
- # Kernel#sleep
29
-
30
- methods = result.threads.first.methods.sort_by {|method_info| method_info.full_name}
31
- # remove methods called by pause/resume
32
- called_methods = ['Array#include?', 'Fixnum#==', 'Kernel#respond_to?', 'Kernel#respond_to_missing?']
33
- methods.reject!{|m| called_methods.include?(m.full_name) }
34
- # TODO: fix pause/resume to not include those methods in the first place
35
- assert_equal(3, methods.length)
36
-
37
- # Check the names
38
- assert_equal('<Class::RubyProf::C1>#sleep_wait', methods[0].full_name)
39
- assert_equal('Kernel#sleep', methods[1].full_name)
40
- assert_equal('PauseResumeTest#test_pause_resume', methods[2].full_name)
41
-
42
- # Check times
43
- assert_in_delta(0.22, methods[0].total_time, 0.02)
44
- assert_in_delta(0, methods[0].wait_time, 0.02)
45
- assert_in_delta(0, methods[0].self_time, 0.02)
46
-
47
- assert_in_delta(0.22, methods[1].total_time, 0.02)
48
- assert_in_delta(0, methods[1].wait_time, 0.02)
49
- assert_in_delta(0.22, methods[1].self_time, 0.02)
50
-
51
- assert_in_delta(0.22, methods[2].total_time, 0.02)
52
- assert_in_delta(0, methods[2].wait_time, 0.02)
53
- assert_in_delta(0, methods[2].self_time, 0.02)
54
- end
55
-
56
- # pause/resume in the same frame
57
- def test_pause_resume_1
58
- profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
59
-
60
- profile.start
61
- method_1a
62
-
63
- profile.pause
64
- method_1b
65
-
66
- profile.resume
67
- method_1c
68
-
69
- result = profile.stop
70
- assert_in_delta(0.65, result.threads[0].methods.select {|m| m.full_name =~ /test_pause_resume_1$/}[0].total_time, 0.05)
71
- end
72
- def method_1a; sleep 0.22 end
73
- def method_1b; sleep 1 end
74
- def method_1c; sleep 0.4 end
75
-
76
- # pause in parent frame, resume in child
77
- def test_pause_resume_2
78
- profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
79
-
80
- profile.start
81
- method_2a
82
-
83
- profile.pause
84
- sleep 0.5
85
- method_2b(profile)
86
-
87
- result = profile.stop
88
- assert_in_delta(0.6, result.threads[0].methods.select{|m| m.full_name =~ /test_pause_resume_2$/}[0].total_time, 0.05)
89
- end
90
- def method_2a; sleep 0.22 end
91
- def method_2b(profile); sleep 0.5; profile.resume; sleep 0.4 end
92
-
93
- # pause in child frame, resume in parent
94
- def test_pause_resume_3
95
- profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
96
-
97
- profile.start
98
- method_3a(profile)
99
-
100
- sleep 0.5
101
- profile.resume
102
- method_3b
103
-
104
- result = profile.stop
105
- assert_in_delta(0.65, result.threads[0].methods.select{|m| m.full_name =~ /test_pause_resume_3$/}[0].total_time, 0.05)
106
- end
107
-
108
- def method_3a(profile)
109
- sleep 0.22
110
- profile.pause
111
- sleep 0.5
112
- end
113
-
114
- def method_3b
115
- sleep 0.4
116
- end
117
-
118
- def test_pause_seq
119
- profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
120
- profile.start ; assert !profile.paused?
121
- profile.pause ; assert profile.paused?
122
- profile.resume; assert !profile.paused?
123
- profile.pause ; assert profile.paused?
124
- profile.pause ; assert profile.paused?
125
- profile.resume; assert !profile.paused?
126
- profile.resume; assert !profile.paused?
127
- profile.stop ; assert !profile.paused?
128
- end
129
-
130
- def test_pause_block
131
- profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
132
- profile.start
133
- profile.pause
134
- assert profile.paused?
135
-
136
- times_block_invoked = 0
137
- retval= profile.resume{
138
- times_block_invoked += 1
139
- 120 + times_block_invoked
140
- }
141
- assert_equal 1, times_block_invoked
142
- assert profile.paused?
143
-
144
- assert_equal 121, retval, "resume() should return the result of the given block."
145
-
146
- profile.stop
147
- end
148
-
149
- def test_pause_block_with_error
150
- profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
151
- profile.start
152
- profile.pause
153
- assert profile.paused?
154
-
155
- begin
156
- profile.resume{ raise }
157
- flunk 'Exception expected.'
158
- rescue
159
- assert profile.paused?
160
- end
161
-
162
- profile.stop
163
- end
164
-
165
- def test_resume_when_not_paused
166
- profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
167
- profile.start ; assert !profile.paused?
168
- profile.resume; assert !profile.paused?
169
- profile.stop ; assert !profile.paused?
170
- end
171
- end
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+ require_relative 'measure_times'
6
+
7
+ class PauseResumeTest < TestCase
8
+ def test_pause_resume
9
+ profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
10
+ # Measured
11
+ profile.start
12
+ RubyProf::C1.sleep_wait
13
+
14
+ # Not measured
15
+ profile.pause
16
+ sleep 1
17
+ RubyProf::C1.sleep_wait
18
+
19
+ # Measured
20
+ profile.resume
21
+ RubyProf::C1.sleep_wait
22
+
23
+ result = profile.stop
24
+
25
+ # Length should be 3:
26
+ # PauseResumeTest#test_pause_resume
27
+ # <Class::RubyProf::C1>#sleep_wait
28
+ # Kernel#sleep
29
+
30
+ methods = result.threads.first.methods.sort_by {|method_info| method_info.full_name}
31
+ # remove methods called by pause/resume
32
+ called_methods = ['Array#include?', 'Fixnum#==', 'Kernel#respond_to?', 'Kernel#respond_to_missing?']
33
+ methods.reject!{|m| called_methods.include?(m.full_name) }
34
+ # TODO: fix pause/resume to not include those methods in the first place
35
+ assert_equal(3, methods.length)
36
+
37
+ # Check the names
38
+ assert_equal('<Class::RubyProf::C1>#sleep_wait', methods[0].full_name)
39
+ assert_equal('Kernel#sleep', methods[1].full_name)
40
+ assert_equal('PauseResumeTest#test_pause_resume', methods[2].full_name)
41
+
42
+ # Check times
43
+ assert_in_delta(0.22, methods[0].total_time, 0.05 * delta_multiplier)
44
+ assert_in_delta(0, methods[0].wait_time, 0.05 * delta_multiplier)
45
+ assert_in_delta(0, methods[0].self_time, 0.05 * delta_multiplier)
46
+
47
+ assert_in_delta(0.22, methods[1].total_time, 0.05 * delta_multiplier)
48
+ assert_in_delta(0, methods[1].wait_time, 0.05 * delta_multiplier)
49
+ assert_in_delta(0.22, methods[1].self_time, 0.05 * delta_multiplier)
50
+
51
+ assert_in_delta(0.22, methods[2].total_time, 0.05 * delta_multiplier)
52
+ assert_in_delta(0, methods[2].wait_time, 0.05 * delta_multiplier)
53
+ assert_in_delta(0, methods[2].self_time, 0.05 * delta_multiplier)
54
+ end
55
+
56
+ # pause/resume in the same frame
57
+ def test_pause_resume_1
58
+ profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
59
+
60
+ profile.start
61
+ method_1a
62
+
63
+ profile.pause
64
+ method_1b
65
+
66
+ profile.resume
67
+ method_1c
68
+
69
+ result = profile.stop
70
+ assert_in_delta(0.65, result.threads[0].methods.select {|m| m.full_name =~ /test_pause_resume_1$/}[0].total_time, 0.05 * delta_multiplier)
71
+ end
72
+ def method_1a; sleep 0.22 end
73
+ def method_1b; sleep 1 end
74
+ def method_1c; sleep 0.4 end
75
+
76
+ # pause in parent frame, resume in child
77
+ def test_pause_resume_2
78
+ profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
79
+
80
+ profile.start
81
+ method_2a
82
+
83
+ profile.pause
84
+ sleep 0.5
85
+ method_2b(profile)
86
+
87
+ result = profile.stop
88
+ assert_in_delta(0.6, result.threads[0].methods.select{|m| m.full_name =~ /test_pause_resume_2$/}[0].total_time, 0.05 * delta_multiplier)
89
+ end
90
+ def method_2a; sleep 0.22 end
91
+ def method_2b(profile); sleep 0.5; profile.resume; sleep 0.4 end
92
+
93
+ # pause in child frame, resume in parent
94
+ def test_pause_resume_3
95
+ profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
96
+
97
+ profile.start
98
+ method_3a(profile)
99
+
100
+ sleep 0.5
101
+ profile.resume
102
+ method_3b
103
+
104
+ result = profile.stop
105
+ assert_in_delta(0.65, result.threads[0].methods.select{|m| m.full_name =~ /test_pause_resume_3$/}[0].total_time, 0.05 * delta_multiplier)
106
+ end
107
+
108
+ def method_3a(profile)
109
+ sleep 0.22
110
+ profile.pause
111
+ sleep 0.5
112
+ end
113
+
114
+ def method_3b
115
+ sleep 0.4
116
+ end
117
+
118
+ def test_pause_seq
119
+ profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
120
+ profile.start ; assert !profile.paused?
121
+ profile.pause ; assert profile.paused?
122
+ profile.resume; assert !profile.paused?
123
+ profile.pause ; assert profile.paused?
124
+ profile.pause ; assert profile.paused?
125
+ profile.resume; assert !profile.paused?
126
+ profile.resume; assert !profile.paused?
127
+ profile.stop ; assert !profile.paused?
128
+ end
129
+
130
+ def test_pause_block
131
+ profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
132
+ profile.start
133
+ profile.pause
134
+ assert profile.paused?
135
+
136
+ times_block_invoked = 0
137
+ retval= profile.resume{
138
+ times_block_invoked += 1
139
+ 120 + times_block_invoked
140
+ }
141
+ assert_equal 1, times_block_invoked
142
+ assert profile.paused?
143
+
144
+ assert_equal 121, retval, "resume() should return the result of the given block."
145
+
146
+ profile.stop
147
+ end
148
+
149
+ def test_pause_block_with_error
150
+ profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
151
+ profile.start
152
+ profile.pause
153
+ assert profile.paused?
154
+
155
+ begin
156
+ profile.resume{ raise }
157
+ flunk 'Exception expected.'
158
+ rescue
159
+ assert profile.paused?
160
+ end
161
+
162
+ profile.stop
163
+ end
164
+
165
+ def test_resume_when_not_paused
166
+ profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
167
+ profile.start ; assert !profile.paused?
168
+ profile.resume; assert !profile.paused?
169
+ profile.stop ; assert !profile.paused?
170
+ end
171
+ end
data/test/prime.rb CHANGED
@@ -1,54 +1,54 @@
1
- # A silly little test program that finds prime numbers. It
2
- # is intentionally badly designed to show off the use
3
- # of ruby-prof.
4
- #
5
- # Source from http://people.cs.uchicago.edu/~bomb154/154/maclabs/profilers-lab/
6
-
7
- def make_random_array(length, maxnum)
8
- result = Array.new(length)
9
- result.each_index do |i|
10
- result[i] = rand(maxnum)
11
- end
12
-
13
- result
14
- end
15
-
16
- def is_prime(x)
17
- y = 2
18
- y.upto(x-1) do |i|
19
- return false if (x % i) == 0
20
- end
21
- true
22
- end
23
-
24
- def find_primes(arr)
25
- result = arr.select do |value|
26
- is_prime(value)
27
- end
28
- result
29
- end
30
-
31
- def find_largest(primes)
32
- largest = primes.first
33
-
34
- # Intentionally use upto for example purposes
35
- # (upto is also called from is_prime)
36
- 0.upto(primes.length-1) do |i|
37
- prime = primes[i]
38
- if prime > largest
39
- largest = prime
40
- end
41
- end
42
- largest
43
- end
44
-
45
- def run_primes(length=10, maxnum=1_000)
46
- # Create random numbers
47
- random_array = make_random_array(length, maxnum)
48
-
49
- # Find the primes
50
- primes = find_primes(random_array)
51
-
52
- # Find the largest primes
53
- find_largest(primes)
54
- end
1
+ # A silly little test program that finds prime numbers. It
2
+ # is intentionally badly designed to show off the use
3
+ # of ruby-prof.
4
+ #
5
+ # Source from http://people.cs.uchicago.edu/~bomb154/154/maclabs/profilers-lab/
6
+
7
+ def make_random_array(length, maxnum)
8
+ result = Array.new(length)
9
+ result.each_index do |i|
10
+ result[i] = rand(maxnum)
11
+ end
12
+
13
+ result
14
+ end
15
+
16
+ def is_prime(x)
17
+ y = 2
18
+ y.upto(x-1) do |i|
19
+ return false if (x % i) == 0
20
+ end
21
+ true
22
+ end
23
+
24
+ def find_primes(arr)
25
+ result = arr.select do |value|
26
+ is_prime(value)
27
+ end
28
+ result
29
+ end
30
+
31
+ def find_largest(primes)
32
+ largest = primes.first
33
+
34
+ # Intentionally use upto for example purposes
35
+ # (upto is also called from is_prime)
36
+ 0.upto(primes.length-1) do |i|
37
+ prime = primes[i]
38
+ if prime > largest
39
+ largest = prime
40
+ end
41
+ end
42
+ largest
43
+ end
44
+
45
+ def run_primes(length=10, maxnum=1_000)
46
+ # Create random numbers
47
+ random_array = make_random_array(length, maxnum)
48
+
49
+ # Find the primes
50
+ primes = find_primes(random_array)
51
+
52
+ # Find the largest primes
53
+ find_largest(primes)
54
+ end
data/test/prime_script.rb CHANGED
@@ -1,6 +1,6 @@
1
- #!/usr/bin/env ruby
2
- # encoding: UTF-8
3
-
4
- # This file is used to test bin/ruby-prof
5
- require_relative './prime'
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ # This file is used to test bin/ruby-prof
5
+ require_relative './prime'
6
6
  run_primes(100, 1_000_000)
@@ -1,27 +1,28 @@
1
- #!/usr/bin/env ruby
2
- # encoding: UTF-8
3
-
4
- require File.expand_path('../test_helper', __FILE__)
5
- require 'fileutils'
6
- require 'tmpdir'
7
- require_relative 'prime'
8
-
9
- # -- Tests ----
10
- class PrinterCallStackTest < TestCase
11
- def setup
12
- super
13
- # WALL_TIME so we can use sleep in our test and get same measurements on linux and windows
14
- @result = RubyProf::Profile.profile(measure_mode: RubyProf::WALL_TIME) do
15
- run_primes(1000, 5000)
16
- end
17
- end
18
-
19
- def test_graph_html_string
20
- output = ''
21
- printer = RubyProf::CallStackPrinter.new(@result)
22
- printer.print(output)
23
-
24
- assert_match(/<!DOCTYPE html>/i, output)
25
- assert_match(/Object#run_primes/i, output)
26
- end
27
- end
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+ require 'fileutils'
6
+ require 'stringio'
7
+ require 'tmpdir'
8
+ require_relative 'prime'
9
+
10
+ # -- Tests ----
11
+ class PrinterCallStackTest < TestCase
12
+ def setup
13
+ super
14
+ # WALL_TIME so we can use sleep in our test and get same measurements on linux and windows
15
+ @result = RubyProf::Profile.profile(measure_mode: RubyProf::WALL_TIME) do
16
+ run_primes(1000, 5000)
17
+ end
18
+ end
19
+
20
+ def test_graph_html_string
21
+ output = StringIO.new
22
+ printer = RubyProf::CallStackPrinter.new(@result)
23
+ printer.print(output)
24
+
25
+ assert_match(/<!DOCTYPE html>/i, output.string)
26
+ assert_match(/Object#run_primes/i, output.string)
27
+ end
28
+ end
@@ -1,30 +1,30 @@
1
- #!/usr/bin/env ruby
2
- # encoding: UTF-8
3
-
4
- require File.expand_path('../test_helper', __FILE__)
5
- require 'fileutils'
6
- require 'tmpdir'
7
- require_relative 'prime'
8
-
9
- # -- Tests ----
10
- class PrinterCallTreeTest < TestCase
11
- def setup
12
- super
13
- # WALL_TIME so we can use sleep in our test and get same measurements on linux and windows
14
- @result = RubyProf::Profile.profile(measure_mode: RubyProf::WALL_TIME) do
15
- run_primes(1000, 5000)
16
- end
17
- end
18
-
19
- def test_call_tree_string
20
- printer = RubyProf::CallTreePrinter.new(@result)
21
-
22
- printer.print(:path => Dir.tmpdir)
23
- main_output_file_name = File.join(Dir.tmpdir, "callgrind.out.#{$$}")
24
- assert(File.exist?(main_output_file_name))
25
- output = File.read(main_output_file_name)
26
- assert_match(/fn=Object::find_primes/i, output)
27
- assert_match(/events: wall_time/i, output)
28
- refute_match(/d\d\d\d\d\d/, output) # old bug looked [in error] like Object::run_primes(d5833116)
29
- end
30
- end
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+ require 'fileutils'
6
+ require 'tmpdir'
7
+ require_relative 'prime'
8
+
9
+ # -- Tests ----
10
+ class PrinterCallTreeTest < TestCase
11
+ def setup
12
+ super
13
+ # WALL_TIME so we can use sleep in our test and get same measurements on linux and windows
14
+ @result = RubyProf::Profile.profile(measure_mode: RubyProf::WALL_TIME) do
15
+ run_primes(1000, 5000)
16
+ end
17
+ end
18
+
19
+ def test_call_tree_string
20
+ printer = RubyProf::CallTreePrinter.new(@result)
21
+
22
+ printer.print(path: Dir.tmpdir)
23
+ main_output_file_name = File.join(Dir.tmpdir, "callgrind.out.#{$$}")
24
+ assert(File.exist?(main_output_file_name))
25
+ output = File.read(main_output_file_name)
26
+ assert_match(/fn=Object::find_primes/i, output)
27
+ assert_match(/events: wall_time/i, output)
28
+ refute_match(/d\d\d\d\d\d/, output) # old bug looked [in error] like Object::run_primes(d5833116)
29
+ end
30
+ end
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+ require 'fileutils'
6
+ require 'stringio'
7
+ require 'tmpdir'
8
+ require_relative 'prime'
9
+
10
+ # -- Tests ----
11
+ class PrinterFlameGraphTest < TestCase
12
+ def setup
13
+ super
14
+ # WALL_TIME so we can use sleep in our test and get same measurements on linux and windows
15
+ @result = RubyProf::Profile.profile(measure_mode: RubyProf::WALL_TIME) do
16
+ run_primes(1000, 5000)
17
+ end
18
+ end
19
+
20
+ def test_flame_graph_string
21
+ output = StringIO.new
22
+ printer = RubyProf::FlameGraphPrinter.new(@result)
23
+ printer.print(output)
24
+
25
+ assert_match(/<!DOCTYPE html>/i, output.string)
26
+ assert_match(/flame-svg/, output.string)
27
+ assert_match(/Object#run_primes/i, output.string)
28
+ end
29
+
30
+ def test_flame_graph_stringio
31
+ output = StringIO.new
32
+ printer = RubyProf::FlameGraphPrinter.new(@result)
33
+ printer.print(output)
34
+
35
+ result = output.string
36
+ assert_match(/<!DOCTYPE html>/i, result)
37
+ assert_match(/flame-svg/, result)
38
+ assert_match(/Object#run_primes/i, result)
39
+ end
40
+
41
+ def test_flame_graph_contains_svg_elements
42
+ output = StringIO.new
43
+ printer = RubyProf::FlameGraphPrinter.new(@result)
44
+ printer.print(output)
45
+
46
+ assert_match(/<svg/, output.string)
47
+ assert_match(/renderNode/, output.string)
48
+ end
49
+
50
+ def test_flame_graph_contains_json_data
51
+ output = StringIO.new
52
+ printer = RubyProf::FlameGraphPrinter.new(@result)
53
+ printer.print(output)
54
+
55
+ # The template embeds thread data as JSON
56
+ assert_match(/"name"/, output.string)
57
+ assert_match(/"value"/, output.string)
58
+ assert_match(/"children"/, output.string)
59
+ end
60
+
61
+ def test_flame_graph_custom_title
62
+ output = StringIO.new
63
+ printer = RubyProf::FlameGraphPrinter.new(@result)
64
+ printer.print(output, title: "Custom Flame Graph")
65
+
66
+ assert_match(/Custom Flame Graph/, output.string)
67
+ end
68
+
69
+ def test_flame_graph_file_output
70
+ Dir.mktmpdir do |dir|
71
+ path = File.join(dir, "flame_graph.html")
72
+ File.open(path, "wb") do |file|
73
+ printer = RubyProf::FlameGraphPrinter.new(@result)
74
+ printer.print(file)
75
+ end
76
+
77
+ content = File.read(path)
78
+ assert_match(/<!DOCTYPE html>/i, content)
79
+ assert_match(/Object#run_primes/i, content)
80
+ end
81
+ end
82
+ end