ruby-prof 1.7.1 → 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 (134) hide show
  1. checksums.yaml +4 -4
  2. data/{CHANGES → CHANGELOG.md} +118 -176
  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/extconf.rb +23 -22
  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.c +296 -296
  40. data/ext/ruby_prof/rp_call_trees.h +25 -28
  41. data/ext/ruby_prof/rp_measure_allocations.c +47 -47
  42. data/ext/ruby_prof/rp_measure_process_time.c +64 -66
  43. data/ext/ruby_prof/rp_measure_wall_time.c +52 -64
  44. data/ext/ruby_prof/rp_measurement.c +0 -5
  45. data/ext/ruby_prof/rp_measurement.h +49 -53
  46. data/ext/ruby_prof/rp_method.c +554 -551
  47. data/ext/ruby_prof/rp_method.h +1 -4
  48. data/ext/ruby_prof/rp_profile.c +1 -1
  49. data/ext/ruby_prof/rp_profile.h +1 -5
  50. data/ext/ruby_prof/rp_stack.c +212 -212
  51. data/ext/ruby_prof/rp_stack.h +50 -53
  52. data/ext/ruby_prof/rp_thread.h +1 -4
  53. data/ext/ruby_prof/ruby_prof.c +50 -50
  54. data/ext/ruby_prof/ruby_prof.h +4 -6
  55. data/ext/ruby_prof/vc/ruby_prof.vcxproj +7 -8
  56. data/lib/ruby-prof/assets/call_stack_printer.html.erb +746 -711
  57. data/lib/ruby-prof/assets/flame_graph_printer.html.erb +412 -0
  58. data/lib/ruby-prof/assets/graph_printer.html.erb +355 -355
  59. data/lib/ruby-prof/call_tree.rb +57 -57
  60. data/lib/ruby-prof/call_tree_visitor.rb +36 -36
  61. data/lib/ruby-prof/exclude_common_methods.rb +204 -204
  62. data/lib/ruby-prof/measurement.rb +17 -17
  63. data/lib/ruby-prof/printers/abstract_printer.rb +142 -138
  64. data/lib/ruby-prof/printers/call_info_printer.rb +53 -53
  65. data/lib/ruby-prof/printers/call_stack_printer.rb +168 -180
  66. data/lib/ruby-prof/printers/call_tree_printer.rb +132 -145
  67. data/lib/ruby-prof/printers/dot_printer.rb +177 -132
  68. data/lib/ruby-prof/printers/flame_graph_printer.rb +79 -0
  69. data/lib/ruby-prof/printers/flat_printer.rb +52 -52
  70. data/lib/ruby-prof/printers/graph_html_printer.rb +62 -63
  71. data/lib/ruby-prof/printers/graph_printer.rb +112 -113
  72. data/lib/ruby-prof/printers/multi_printer.rb +134 -127
  73. data/lib/ruby-prof/profile.rb +13 -0
  74. data/lib/ruby-prof/rack.rb +114 -105
  75. data/lib/ruby-prof/task.rb +147 -147
  76. data/lib/ruby-prof/thread.rb +20 -20
  77. data/lib/ruby-prof/version.rb +3 -3
  78. data/lib/ruby-prof.rb +50 -52
  79. data/lib/unprof.rb +10 -10
  80. data/ruby-prof.gemspec +66 -65
  81. data/test/abstract_printer_test.rb +25 -27
  82. data/test/alias_test.rb +203 -117
  83. data/test/call_tree_builder.rb +126 -126
  84. data/test/call_tree_visitor_test.rb +27 -27
  85. data/test/call_trees_test.rb +66 -66
  86. data/test/duplicate_names_test.rb +32 -32
  87. data/test/dynamic_method_test.rb +50 -62
  88. data/test/enumerable_test.rb +23 -21
  89. data/test/exceptions_test.rb +24 -24
  90. data/test/exclude_methods_test.rb +363 -257
  91. data/test/exclude_threads_test.rb +48 -48
  92. data/test/fiber_test.rb +195 -195
  93. data/test/gc_test.rb +104 -102
  94. data/test/inverse_call_tree_test.rb +174 -174
  95. data/test/line_number_test.rb +563 -289
  96. data/test/marshal_test.rb +144 -145
  97. data/test/measure_allocations.rb +26 -26
  98. data/test/measure_allocations_test.rb +1511 -1081
  99. data/test/measure_process_time_test.rb +3286 -2477
  100. data/test/measure_times.rb +56 -56
  101. data/test/measure_wall_time_test.rb +773 -568
  102. data/test/measurement_test.rb +82 -82
  103. data/test/merge_test.rb +146 -146
  104. data/test/method_info_test.rb +100 -95
  105. data/test/multi_printer_test.rb +52 -66
  106. data/test/no_method_class_test.rb +15 -15
  107. data/test/pause_resume_test.rb +171 -171
  108. data/test/prime.rb +54 -54
  109. data/test/prime_script.rb +5 -5
  110. data/test/printer_call_stack_test.rb +28 -27
  111. data/test/printer_call_tree_test.rb +30 -30
  112. data/test/printer_flame_graph_test.rb +82 -0
  113. data/test/printer_flat_test.rb +99 -99
  114. data/test/printer_graph_html_test.rb +62 -59
  115. data/test/printer_graph_test.rb +42 -40
  116. data/test/printers_test.rb +162 -135
  117. data/test/printing_recursive_graph_test.rb +81 -81
  118. data/test/profile_test.rb +101 -101
  119. data/test/rack_test.rb +103 -93
  120. data/test/recursive_test.rb +796 -622
  121. data/test/scheduler.rb +4 -0
  122. data/test/singleton_test.rb +39 -38
  123. data/test/stack_printer_test.rb +61 -61
  124. data/test/start_stop_test.rb +106 -106
  125. data/test/test_helper.rb +24 -20
  126. data/test/thread_test.rb +229 -231
  127. data/test/unique_call_path_test.rb +123 -136
  128. data/test/yarv_test.rb +56 -60
  129. metadata +68 -16
  130. data/ext/ruby_prof/rp_measure_memory.c +0 -46
  131. data/lib/ruby-prof/compatibility.rb +0 -113
  132. data/test/compatibility_test.rb +0 -49
  133. data/test/crash2.rb +0 -144
  134. data/test/measure_memory_test.rb +0 -1456
@@ -1,113 +0,0 @@
1
- # encoding: utf-8
2
-
3
- # These methods are deprecated and are available for backwards compatability.
4
- module RubyProf
5
- # call-seq:
6
- # measure_mode -> measure_mode
7
- #
8
- # Returns what ruby-prof is measuring. Valid values include:
9
- #
10
- # * RubyProf::WALL_TIME
11
- # * RubyProf::PROCESS_TIME
12
- # * RubyProf::ALLOCATIONS
13
- # * RubyProf::MEMORY
14
- def self.measure_mode
15
- @measure_mode ||= RubyProf::WALL_TIME
16
- end
17
-
18
- # call-seq:
19
- # measure_mode=value -> void
20
- #
21
- # Specifies what ruby-prof should measure. Valid values include:
22
- #
23
- # * RubyProf::WALL_TIME - Wall time measures the real-world time elapsed between any two moments. If there are other processes concurrently running on the system that use significant CPU or disk time during a profiling run then the reported results will be larger than expected. On Windows, wall time is measured using GetTickCount(), on MacOS by mach_absolute_time, on Linux by clock_gettime and otherwise by gettimeofday.
24
- # * RubyProf::PROCESS_TIME - Process time measures the time used by a process between any two moments. It is unaffected by other processes concurrently running on the system. Remember with process time that calls to methods like sleep will not be included in profiling results. On Windows, process time is measured using GetProcessTimes and on other platforms by clock_gettime.
25
- # * RubyProf::ALLOCATIONS - Object allocations measures show how many objects each method in a program allocates. Measurements are done via Ruby's GC.stat api.
26
- # * RubyProf::MEMORY - Memory measures how much memory each method in a program uses. Measurements are done via Ruby's TracePoint api.
27
- def self.measure_mode=(value)
28
- @measure_mode = value
29
- end
30
-
31
- # Returns the threads that ruby-prof should exclude from profiling
32
- def self.exclude_threads
33
- @exclude_threads ||= Array.new
34
- end
35
-
36
- # Specifies which threads ruby-prof should exclude from profiling
37
- def self.exclude_threads=(value)
38
- @exclude_threads = value
39
- end
40
-
41
- # Starts profiling
42
- def self.start
43
- ensure_not_running!
44
- @profile = Profile.new(:measure_mode => measure_mode, :exclude_threads => exclude_threads)
45
- @profile.start
46
- end
47
-
48
- # Pauses profiling
49
- def self.pause
50
- ensure_running!
51
- @profile.pause
52
- end
53
-
54
- # Is a profile running?
55
- def self.running?
56
- if defined?(@profile) and @profile
57
- @profile.running?
58
- else
59
- false
60
- end
61
- end
62
-
63
- # Resume profiling
64
- def self.resume
65
- ensure_running!
66
- @profile.resume
67
- end
68
-
69
- # Stops profiling
70
- def self.stop
71
- ensure_running!
72
- result = @profile.stop
73
- @profile = nil
74
- result
75
- end
76
-
77
- # Profiles a block
78
- def self.profile(options = {}, &block)
79
- ensure_not_running!
80
- options = {:measure_mode => measure_mode, :exclude_threads => exclude_threads }.merge!(options)
81
- Profile.profile(options, &block)
82
- end
83
-
84
- # :nodoc:
85
- def self.start_script(script)
86
- start
87
- load script
88
- end
89
-
90
- private
91
-
92
- def self.ensure_running!
93
- raise(RuntimeError, "RubyProf.start was not yet called") unless running?
94
- end
95
-
96
- def self.ensure_not_running!
97
- raise(RuntimeError, "RubyProf is already running") if running?
98
- end
99
-
100
- class << self
101
- extend Gem::Deprecate
102
- deprecate :measure_mode, "RubyProf::Profile#measure_mode", 2023, 6
103
- deprecate :measure_mode=, "RubyProf::Profile#measure_mode=", 2023, 6
104
- deprecate :exclude_threads, "RubyProf::Profile#exclude_threads", 2023, 6
105
- deprecate :exclude_threads=, "RubyProf::Profile#initialize", 2023, 6
106
- deprecate :start, "RubyProf::Profile#start", 2023, 6
107
- deprecate :pause, "RubyProf::Profile#pause", 2023, 6
108
- deprecate :stop, "RubyProf::Profile#stop", 2023, 6
109
- deprecate :resume, "RubyProf::Profile#resume", 2023, 6
110
- deprecate :running?, "RubyProf::Profile#running?", 2023, 6
111
- deprecate :profile, "RubyProf::Profile.profile", 2023, 6
112
- end
113
- end
@@ -1,49 +0,0 @@
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 CompatibilityTest < TestCase
8
- def setup
9
- super
10
- Gem::Deprecate.skip = true
11
- RubyProf::measure_mode = RubyProf::WALL_TIME
12
- end
13
-
14
- def teardown
15
- super
16
- Gem::Deprecate.skip = false
17
- end
18
-
19
- def test_running
20
- assert(!RubyProf.running?)
21
- RubyProf.start
22
- assert(RubyProf.running?)
23
- RubyProf.stop
24
- assert(!RubyProf.running?)
25
- end
26
-
27
- def test_double_profile
28
- RubyProf.start
29
- assert_raises(RuntimeError) do
30
- RubyProf.start
31
- end
32
- RubyProf.stop
33
- end
34
-
35
- def test_no_block
36
- assert_raises(ArgumentError) do
37
- RubyProf.profile
38
- end
39
- end
40
-
41
- def test_traceback
42
- RubyProf.start
43
- assert_raises(NoMethodError) do
44
- RubyProf.xxx
45
- end
46
-
47
- RubyProf.stop
48
- end
49
- end
data/test/crash2.rb DELETED
@@ -1,144 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- # This is a benchmark for HTTPS traffic.
5
- # To run against a local server:
6
- # docker run --rm --detach --name httpbin -v /tmp:/tmp -v $PWD/tests/data:/data -e HTTPS_CERT_FILE='/data/127.0.0.1.cert.crt' -e HTTPS_KEY_FILE='/data/127.0.0.1.cert.key' -e PORT='8443' -p 8443:8443 mccutchen/go-httpbin
7
- # Then, run the benchmark:
8
- # benchmarks/httpbin.rb --uri='https://localhost:8443/stream-bytes/102400?chunk_size=1024'
9
- # Finally, stop the server with:
10
- # docker kill httpbin
11
-
12
- #require 'bundler/inline'
13
-
14
- #gemfile do
15
- # source 'https://rubygems.org'
16
-
17
- # gem 'benchmark-ips', require: 'benchmark/ips'
18
- # gem 'ruby-prof', '1.6.3'
19
- # gem 'excon'
20
- #end
21
-
22
- require File.expand_path('../test_helper', __FILE__)
23
-
24
-
25
- require 'openssl'
26
- require 'optparse'
27
- require 'uri'
28
- require 'excon'
29
- require 'benchmark'
30
- require 'benchmark/ips'
31
-
32
- Options = Struct.new(:uri, :profile, :time, :warmup, :iterations, :status)
33
-
34
- options = Options.new(
35
- URI.parse('https://httpbingo.org/stream-bytes/102400?chunk_size=1024'),
36
- false,
37
- 10,
38
- 5,
39
- 2,
40
- 200
41
- )
42
-
43
- OptionParser.new do |opts|
44
- opts.banner = "Usage: ruby #{__FILE__} [options]"
45
-
46
- opts.on('-u URI', '--uri=URI', String, "URI to send requests to (default: #{options.uri})") do |uri|
47
- options.uri = URI.parse(uri)
48
- end
49
-
50
- opts.on('-p', '--[no-]profile', 'Profile the benchmark using Ruby-Prof (defaults to no profiling)') do |profile|
51
- options.profile = profile
52
- end
53
-
54
- opts.on('-t TIME', '--time=TIME', Float, "The number of seconds to run the benchmark to measure performance (default: #{options.time})") do |time|
55
- options.time = time
56
- end
57
-
58
- opts.on('-w WARMUP', '--warmup=WARMUP', Float, "The number of seconds to warmup the benchmark for before measuring (default: #{options.warmup})") do |warmup|
59
- options.warmup = warmup
60
- end
61
-
62
- opts.on('-i ITERATIONS', '--iterations=ITERATIONS', Integer, "The number of iterations to run the benchmark for (default: #{options.iterations})") do |iterations|
63
- options.iterations = iterations
64
- end
65
-
66
- opts.on('-s STATUS', '--status=STATUS', Integer, "The HTTP status expected from a request to the given URI (default: #{options.status})") do |status|
67
- options.status = status
68
- end
69
-
70
- opts.on('-h', '--help', 'print options') do
71
- puts opts
72
- exit
73
- end
74
- end.parse!
75
-
76
- # Enable and start GC before each job run. Disable GC afterwards.
77
- #
78
- # Inspired by https://www.omniref.com/ruby/2.2.1/symbols/Benchmark/bm?#annotation=4095926&line=182
79
- class GCSuite
80
- def warming(*)
81
- run_gc
82
- end
83
-
84
- def running(*)
85
- run_gc
86
- end
87
-
88
- def warmup_stats(*); end
89
-
90
- def add_report(*); end
91
-
92
- private
93
-
94
- def run_gc
95
- GC.enable
96
- GC.start
97
- GC.compact
98
- GC.disable
99
- end
100
- end
101
-
102
- profile = nil
103
-
104
- if options.profile
105
- profile = RubyProf::Profile.new(track_allocations: true, measure_mode: RubyProf::MEMORY)
106
- profile.start
107
- profile.pause
108
- end
109
-
110
- excerpt = ['Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.']
111
- data = (excerpt * 3).join(' ')
112
-
113
- client = ::Excon.new(options.uri.to_s, ssl_verify_peer: false, ssl_verify_peer_host: false, persistent: true, retry_errors: [Excon::Error::Socket], idempotent: true)
114
-
115
- Benchmark.ips do |x|
116
- x.time = options.time
117
- x.warmup = options.warmup
118
- x.suite = GCSuite.new
119
- x.iterations = options.iterations
120
-
121
- x.report(options.uri.to_s) do
122
- profile&.resume
123
-
124
- response = client.request(method: :get, headers: { data: data })
125
-
126
- response.body
127
- response.status
128
-
129
- profile&.pause
130
-
131
- raise "Invalid status: expected #{options.status}, actual is #{response.status}" unless response.status == options.status
132
- end
133
-
134
- x.compare!
135
- end
136
-
137
- if options.profile
138
- result = profile.stop
139
-
140
- File.open("excon-#{Excon::VERSION}.html", 'w') do |output|
141
- printer = RubyProf::GraphHtmlPrinter.new(result)
142
- printer.print(output)
143
- end
144
- end