ruby-prof 2.0.4 → 2.0.5

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 (85) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -2
  3. data/lib/ruby-prof/printers/flame_graph_printer.rb +80 -78
  4. data/lib/ruby-prof/version.rb +1 -1
  5. metadata +4 -85
  6. data/Rakefile +0 -98
  7. data/docs/advanced-usage.md +0 -132
  8. data/docs/alternatives.md +0 -98
  9. data/docs/architecture.md +0 -304
  10. data/docs/best-practices.md +0 -27
  11. data/docs/getting-started.md +0 -130
  12. data/docs/history.md +0 -11
  13. data/docs/index.md +0 -45
  14. data/docs/profiling-rails.md +0 -64
  15. data/docs/public/examples/example.rb +0 -33
  16. data/docs/public/examples/generate_reports.rb +0 -92
  17. data/docs/public/examples/reports/call_info.txt +0 -27
  18. data/docs/public/examples/reports/call_stack.html +0 -835
  19. data/docs/public/examples/reports/callgrind.out +0 -150
  20. data/docs/public/examples/reports/flame_graph.html +0 -408
  21. data/docs/public/examples/reports/flat.txt +0 -45
  22. data/docs/public/examples/reports/graph.dot +0 -129
  23. data/docs/public/examples/reports/graph.html +0 -1319
  24. data/docs/public/examples/reports/graph.txt +0 -100
  25. data/docs/public/examples/reports/graphviz_viewer.html +0 -1
  26. data/docs/public/images/call_stack.png +0 -0
  27. data/docs/public/images/class_diagram.png +0 -0
  28. data/docs/public/images/dot_printer.png +0 -0
  29. data/docs/public/images/flame_graph.png +0 -0
  30. data/docs/public/images/flat.png +0 -0
  31. data/docs/public/images/graph.png +0 -0
  32. data/docs/public/images/graph_html.png +0 -0
  33. data/docs/public/images/ruby-prof-logo.svg +0 -1
  34. data/docs/reports.md +0 -151
  35. data/docs/stylesheets/extra.css +0 -80
  36. data/ruby-prof.gemspec +0 -66
  37. data/test/abstract_printer_test.rb +0 -25
  38. data/test/alias_test.rb +0 -203
  39. data/test/call_tree_builder.rb +0 -126
  40. data/test/call_tree_test.rb +0 -94
  41. data/test/call_tree_visitor_test.rb +0 -27
  42. data/test/call_trees_test.rb +0 -66
  43. data/test/duplicate_names_test.rb +0 -32
  44. data/test/dynamic_method_test.rb +0 -50
  45. data/test/enumerable_test.rb +0 -23
  46. data/test/exceptions_test.rb +0 -24
  47. data/test/exclude_methods_test.rb +0 -363
  48. data/test/exclude_threads_test.rb +0 -48
  49. data/test/fiber_test.rb +0 -195
  50. data/test/gc_test.rb +0 -104
  51. data/test/inverse_call_tree_test.rb +0 -174
  52. data/test/line_number_test.rb +0 -563
  53. data/test/marshal_test.rb +0 -144
  54. data/test/measure_allocations.rb +0 -26
  55. data/test/measure_allocations_test.rb +0 -1511
  56. data/test/measure_process_time_test.rb +0 -3286
  57. data/test/measure_times.rb +0 -56
  58. data/test/measure_wall_time_test.rb +0 -774
  59. data/test/measurement_test.rb +0 -82
  60. data/test/merge_test.rb +0 -146
  61. data/test/method_info_test.rb +0 -100
  62. data/test/multi_printer_test.rb +0 -52
  63. data/test/no_method_class_test.rb +0 -15
  64. data/test/pause_resume_test.rb +0 -171
  65. data/test/prime.rb +0 -54
  66. data/test/prime_script.rb +0 -6
  67. data/test/printer_call_stack_test.rb +0 -28
  68. data/test/printer_call_tree_test.rb +0 -30
  69. data/test/printer_flame_graph_test.rb +0 -82
  70. data/test/printer_flat_test.rb +0 -110
  71. data/test/printer_graph_html_test.rb +0 -62
  72. data/test/printer_graph_test.rb +0 -42
  73. data/test/printers_test.rb +0 -162
  74. data/test/printing_recursive_graph_test.rb +0 -81
  75. data/test/profile_test.rb +0 -101
  76. data/test/rack_test.rb +0 -103
  77. data/test/recursive_test.rb +0 -796
  78. data/test/scheduler.rb +0 -367
  79. data/test/singleton_test.rb +0 -39
  80. data/test/stack_printer_test.rb +0 -61
  81. data/test/start_stop_test.rb +0 -106
  82. data/test/test_helper.rb +0 -24
  83. data/test/thread_test.rb +0 -229
  84. data/test/unique_call_path_test.rb +0 -123
  85. data/test/yarv_test.rb +0 -56
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9994be0a9bf3c5d097d5064e0c950b6f494acd4cd2fd288fd8bb8c64c3a4a854
4
- data.tar.gz: 13fef04d65fb66ce56c0eb32e2d03071f757776e048fcc1c39afdeb2e9af1951
3
+ metadata.gz: bea4b44182333b828042bdc616b790f75c5153b8e6685ce009e1544e0ae72a77
4
+ data.tar.gz: 19d0c19e31d7d28cb49e7e962425d16b841fe2ac62e7ad033a6ec6d4be7367ae
5
5
  SHA512:
6
- metadata.gz: 4967192c074e787a847cba962eb93e7bfc890ad91aa2d92becf151c726979e1944e46bd4196d63192c35e4067742019ebc4b6450e07d7b047c722924f9d61ab8
7
- data.tar.gz: 98a6be45f8b4597ffa66d5ef4f679ce1b99e7e2563853f496c84733c9954dc77a70284ec06d682031119f7069107b7557b628c9ca899059543971d1f6eae7b74
6
+ metadata.gz: a50821527f7cc6a24af9d167cb9b3c68d076b53ce495c1d2efde4cf90f6b90775e14f1599df660c4f0fddfc7f2c1274065a6bead8e0cd4dd8916ff2b11e65b4e
7
+ data.tar.gz: d43d3352a8d7a1d275621e5eea0c4c251f2084725317ac0e0120202dbcebd25654d433ca01e1de3567d99389585fb76805b80d677a3442a3da1ca1b46c8962c2
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.5 (2026-06-21)
4
+ * Fix FlameGraphPrinter crashing with `JSON::NestingError` on deep call trees (issue #353)
5
+ * Fix link to API documentation (issue #351)
6
+
3
7
  ## 2.0.4 (2026-03-03)
4
8
  * Fix NoMethodError when sort_method is nil (issue #349)
5
9
  * Fix broken source_code_uri on rubygems.org (issue #350)
@@ -28,7 +32,7 @@
28
32
 
29
33
  ### Backwards Incompatible Changes
30
34
  * Removed `RubyProf::MEMORY` measurement mode (no longer works on Ruby 4.0+)
31
- * Rremove compatibility API that was scheduled for removal in 2023
35
+ * Remove compatibility API that was scheduled for removal in 2023
32
36
  * Printer options now use keyword arguments instead of an options hash. For example:
33
37
  ```ruby
34
38
  # Before:
@@ -162,7 +166,7 @@ Changes (Charlie Savage):
162
166
 
163
167
  * Profiling is significantly faster - 5x in some cases
164
168
  * Recursive profiles are finally handled correctly. Yeah!!!
165
- * Redesigned reports (Chirs Whitefield)
169
+ * Redesigned reports (Chris Whitefield)
166
170
  * New documentation website (https://ruby-prof.github.io)
167
171
  * The ability to measure allocations and memory usage using a standard (unpatched) version of ruby
168
172
  * The ability to save and reload profiling results for later analysis
@@ -1,78 +1,80 @@
1
- # encoding: utf-8
2
-
3
- require 'erb'
4
- require 'json'
5
-
6
- module RubyProf
7
- # Prints a HTML flame graph visualization of the call tree.
8
- #
9
- # To use the printer:
10
- #
11
- # result = RubyProf.profile do
12
- # [code to profile]
13
- # end
14
- #
15
- # printer = RubyProf::FlameGraphPrinter.new(result)
16
- # printer.print(STDOUT)
17
-
18
- class FlameGraphPrinter < AbstractPrinter
19
- include ERB::Util
20
-
21
- # Specify print options.
22
- #
23
- # output - Any IO object, including STDOUT or a file.
24
- #
25
- # Keyword arguments:
26
- # title: - a String to override the default "ruby-prof flame graph"
27
- # title of the report.
28
- #
29
- # Also accepts min_percent:, max_percent:, filter_by:, and sort_method:
30
- # from AbstractPrinter.
31
- def print(output = STDOUT, title: "ruby-prof flame graph",
32
- min_percent: 0, max_percent: 100, filter_by: :self_time, sort_method: nil, max_depth: nil, **)
33
- @min_percent = min_percent
34
- @max_percent = max_percent
35
- @filter_by = filter_by
36
- @sort_method = sort_method
37
- @max_depth = max_depth
38
- @title = title
39
- output << ERB.new(self.template).result(binding)
40
- end
41
-
42
- attr_reader :title
43
-
44
- def build_flame_data(call_tree, depth = 0)
45
- node = {
46
- name: call_tree.target.full_name,
47
- value: call_tree.total_time,
48
- self_value: call_tree.self_time,
49
- called: call_tree.called,
50
- children: []
51
- }
52
-
53
- if @max_depth.nil? || depth < @max_depth
54
- call_tree.children.each do |child|
55
- node[:children] << build_flame_data(child, depth + 1)
56
- end
57
- end
58
-
59
- node
60
- end
61
-
62
- def flame_data_json
63
- threads = @result.threads.map do |thread|
64
- {
65
- id: thread.id,
66
- fiber_id: thread.fiber_id,
67
- total_time: thread.total_time,
68
- data: build_flame_data(thread.call_tree)
69
- }
70
- end
71
- JSON.generate(threads)
72
- end
73
-
74
- def template
75
- open_asset('flame_graph_printer.html.erb')
76
- end
77
- end
78
- end
1
+ # encoding: utf-8
2
+
3
+ require 'erb'
4
+ require 'json'
5
+
6
+ module RubyProf
7
+ # Prints a HTML flame graph visualization of the call tree.
8
+ #
9
+ # To use the printer:
10
+ #
11
+ # result = RubyProf.profile do
12
+ # [code to profile]
13
+ # end
14
+ #
15
+ # printer = RubyProf::FlameGraphPrinter.new(result)
16
+ # printer.print(STDOUT)
17
+
18
+ class FlameGraphPrinter < AbstractPrinter
19
+ include ERB::Util
20
+
21
+ # Specify print options.
22
+ #
23
+ # output - Any IO object, including STDOUT or a file.
24
+ #
25
+ # Keyword arguments:
26
+ # title: - a String to override the default "ruby-prof flame graph"
27
+ # title of the report.
28
+ #
29
+ # Also accepts min_percent:, max_percent:, filter_by:, and sort_method:
30
+ # from AbstractPrinter.
31
+ def print(output = STDOUT, title: "ruby-prof flame graph",
32
+ min_percent: 0, max_percent: 100, filter_by: :self_time, sort_method: nil, max_depth: nil, **)
33
+ @min_percent = min_percent
34
+ @max_percent = max_percent
35
+ @filter_by = filter_by
36
+ @sort_method = sort_method
37
+ @max_depth = max_depth
38
+ @title = title
39
+ output << ERB.new(self.template).result(binding)
40
+ end
41
+
42
+ attr_reader :title
43
+
44
+ def build_flame_data(call_tree, depth = 0)
45
+ node = {
46
+ name: call_tree.target.full_name,
47
+ value: call_tree.total_time,
48
+ self_value: call_tree.self_time,
49
+ called: call_tree.called,
50
+ children: []
51
+ }
52
+
53
+ if @max_depth.nil? || depth < @max_depth
54
+ call_tree.children.each do |child|
55
+ node[:children] << build_flame_data(child, depth + 1)
56
+ end
57
+ end
58
+
59
+ node
60
+ end
61
+
62
+ def flame_data_json
63
+ threads = @result.threads.map do |thread|
64
+ {
65
+ id: thread.id,
66
+ fiber_id: thread.fiber_id,
67
+ total_time: thread.total_time,
68
+ data: build_flame_data(thread.call_tree)
69
+ }
70
+ end
71
+ # Disable JSON nesting limit (default 100) so deep call trees serialize.
72
+ # See https://github.com/ruby-prof/ruby-prof/issues/353
73
+ JSON.generate(threads, max_nesting: false)
74
+ end
75
+
76
+ def template
77
+ open_asset('flame_graph_printer.html.erb')
78
+ end
79
+ end
80
+ end
@@ -1,3 +1,3 @@
1
1
  module RubyProf
2
- VERSION = "2.0.4"
2
+ VERSION = "2.0.5"
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-prof
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.4
4
+ version: 2.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shugo Maeda, Charlie Savage, Roger Pack, Stefan Kaes
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-03-03 00:00:00.000000000 Z
10
+ date: 2026-06-21 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: base64
@@ -97,38 +97,8 @@ files:
97
97
  - CHANGELOG.md
98
98
  - LICENSE
99
99
  - README.md
100
- - Rakefile
101
100
  - bin/ruby-prof
102
101
  - bin/ruby-prof-check-trace
103
- - docs/advanced-usage.md
104
- - docs/alternatives.md
105
- - docs/architecture.md
106
- - docs/best-practices.md
107
- - docs/getting-started.md
108
- - docs/history.md
109
- - docs/index.md
110
- - docs/profiling-rails.md
111
- - docs/public/examples/example.rb
112
- - docs/public/examples/generate_reports.rb
113
- - docs/public/examples/reports/call_info.txt
114
- - docs/public/examples/reports/call_stack.html
115
- - docs/public/examples/reports/callgrind.out
116
- - docs/public/examples/reports/flame_graph.html
117
- - docs/public/examples/reports/flat.txt
118
- - docs/public/examples/reports/graph.dot
119
- - docs/public/examples/reports/graph.html
120
- - docs/public/examples/reports/graph.txt
121
- - docs/public/examples/reports/graphviz_viewer.html
122
- - docs/public/images/call_stack.png
123
- - docs/public/images/class_diagram.png
124
- - docs/public/images/dot_printer.png
125
- - docs/public/images/flame_graph.png
126
- - docs/public/images/flat.png
127
- - docs/public/images/graph.png
128
- - docs/public/images/graph_html.png
129
- - docs/public/images/ruby-prof-logo.svg
130
- - docs/reports.md
131
- - docs/stylesheets/extra.css
132
102
  - ext/ruby_prof/extconf.rb
133
103
  - ext/ruby_prof/rp_allocation.c
134
104
  - ext/ruby_prof/rp_allocation.h
@@ -179,56 +149,6 @@ files:
179
149
  - lib/ruby-prof/thread.rb
180
150
  - lib/ruby-prof/version.rb
181
151
  - lib/unprof.rb
182
- - ruby-prof.gemspec
183
- - test/abstract_printer_test.rb
184
- - test/alias_test.rb
185
- - test/call_tree_builder.rb
186
- - test/call_tree_test.rb
187
- - test/call_tree_visitor_test.rb
188
- - test/call_trees_test.rb
189
- - test/duplicate_names_test.rb
190
- - test/dynamic_method_test.rb
191
- - test/enumerable_test.rb
192
- - test/exceptions_test.rb
193
- - test/exclude_methods_test.rb
194
- - test/exclude_threads_test.rb
195
- - test/fiber_test.rb
196
- - test/gc_test.rb
197
- - test/inverse_call_tree_test.rb
198
- - test/line_number_test.rb
199
- - test/marshal_test.rb
200
- - test/measure_allocations.rb
201
- - test/measure_allocations_test.rb
202
- - test/measure_process_time_test.rb
203
- - test/measure_times.rb
204
- - test/measure_wall_time_test.rb
205
- - test/measurement_test.rb
206
- - test/merge_test.rb
207
- - test/method_info_test.rb
208
- - test/multi_printer_test.rb
209
- - test/no_method_class_test.rb
210
- - test/pause_resume_test.rb
211
- - test/prime.rb
212
- - test/prime_script.rb
213
- - test/printer_call_stack_test.rb
214
- - test/printer_call_tree_test.rb
215
- - test/printer_flame_graph_test.rb
216
- - test/printer_flat_test.rb
217
- - test/printer_graph_html_test.rb
218
- - test/printer_graph_test.rb
219
- - test/printers_test.rb
220
- - test/printing_recursive_graph_test.rb
221
- - test/profile_test.rb
222
- - test/rack_test.rb
223
- - test/recursive_test.rb
224
- - test/scheduler.rb
225
- - test/singleton_test.rb
226
- - test/stack_printer_test.rb
227
- - test/start_stop_test.rb
228
- - test/test_helper.rb
229
- - test/thread_test.rb
230
- - test/unique_call_path_test.rb
231
- - test/yarv_test.rb
232
152
  homepage: https://github.com/ruby-prof/ruby-prof
233
153
  licenses:
234
154
  - BSD-2-Clause
@@ -236,7 +156,7 @@ metadata:
236
156
  bug_tracker_uri: https://github.com/ruby-prof/ruby-prof/issues
237
157
  changelog_uri: https://github.com/ruby-prof/ruby-prof/blob/master/CHANGELOG.md
238
158
  documentation_uri: https://ruby-prof.github.io/
239
- source_code_uri: https://github.com/ruby-prof/ruby-prof/tree/2.0.4
159
+ source_code_uri: https://github.com/ruby-prof/ruby-prof/tree/2.0.5
240
160
  rdoc_options: []
241
161
  require_paths:
242
162
  - lib
@@ -254,5 +174,4 @@ requirements: []
254
174
  rubygems_version: 4.0.6
255
175
  specification_version: 4
256
176
  summary: Fast Ruby profiler
257
- test_files:
258
- - test/test_helper.rb
177
+ test_files: []
data/Rakefile DELETED
@@ -1,98 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require "rubygems/package_task"
4
- require "rake/extensiontask"
5
- require "rake/testtask"
6
- require "rdoc/task"
7
- require "date"
8
- require "rake/clean"
9
-
10
- # To release a version of ruby-prof:
11
- # * Update lib/ruby-prof/version.rb
12
- # * Update CHANGES
13
- # * git commit to commit files
14
- # * rake clobber to remove extra files
15
- # * rake compile to build windows gems
16
- # * rake package to create the gems
17
- # * Tag the release (git tag 0.10.1)
18
- # * Push to ruybgems.org (gem push pkg/<gem files>)
19
-
20
- GEM_NAME = 'ruby-prof'
21
- SO_NAME = 'ruby_prof'
22
-
23
- default_spec = Gem::Specification.load("#{GEM_NAME}.gemspec")
24
-
25
- # specify which versions/builds to cross compile
26
- Rake::ExtensionTask.new do |ext|
27
- ext.gem_spec = default_spec
28
- ext.name = SO_NAME
29
- ext.ext_dir = "ext/#{SO_NAME}"
30
- ext.lib_dir = "lib/#{Gem::Version.new(RUBY_VERSION).segments[0..1].join('.')}"
31
- ext.cross_compile = true
32
- ext.cross_platform = ['x64-mingw32']
33
- end
34
-
35
- # Rake task to build the default package
36
- Gem::PackageTask.new(default_spec) do |pkg|
37
- pkg.need_tar = true
38
- end
39
-
40
- # make sure rdoc has been built when packaging
41
- # why do we ship rdoc as part of the gem?
42
- Rake::Task[:package].enhance [:rdoc]
43
-
44
- # Setup Windows Gem
45
- if RUBY_PLATFORM.match(/mswin|mingw/)
46
- # Windows specification
47
- win_spec = default_spec.clone
48
- win_spec.platform = Gem::Platform::CURRENT
49
- win_spec.files += Dir.glob('lib/**/*.so')
50
-
51
- # Unset extensions
52
- win_spec.extensions = nil
53
-
54
- # Rake task to build the windows package
55
- Gem::PackageTask.new(win_spec) do |pkg|
56
- pkg.need_tar = false
57
- end
58
- end
59
-
60
- # --------- RDoc Documentation ------
61
- desc "Generate rdoc documentation"
62
- RDoc::Task.new("rdoc") do |rdoc|
63
- rdoc.rdoc_dir = 'doc'
64
- rdoc.title = "ruby-prof"
65
- # Show source inline with line numbers
66
- rdoc.options << "--line-numbers"
67
- # Make the readme file the start page for the generated html
68
- rdoc.options << '--main' << 'README.md'
69
- rdoc.rdoc_files.include('bin/*',
70
- 'doc/*.rdoc',
71
- 'lib/**/*.rb',
72
- 'ext/ruby_prof/*.c',
73
- 'ext/ruby_prof/*.h',
74
- 'README.md',
75
- 'LICENSE')
76
- end
77
-
78
- task :default => :test
79
-
80
- for file in Dir['lib/**/*.{o,so,bundle}']
81
- CLEAN.include file
82
- end
83
- for file in Dir['doc/**/*.{txt,dat,png,html}']
84
- CLEAN.include file
85
- end
86
- CLEAN.reject!{|f| !File.exist?(f)}
87
- task :clean do
88
- # remove tmp dir contents completely after cleaning
89
- FileUtils.rm_rf('tmp/*')
90
- end
91
-
92
- desc 'Run the ruby-prof test suite'
93
- Rake::TestTask.new do |t|
94
- t.libs += %w(lib ext test)
95
- t.test_files = Dir['test/**_test.rb']
96
- t.verbose = true
97
- t.warning = true
98
- end
@@ -1,132 +0,0 @@
1
- # Advanced Usage
2
-
3
- This section describes advanced usage of ruby-prof. Additional documentation for every class is also [available](index.md#api-documentation). For workflow guidance, see [Best Practices](best-practices.md).
4
-
5
- ## Profiling Options
6
-
7
- ruby-prof understands the following options when profiling code:
8
-
9
- **measure_mode** - What ruby-prof should measure. For more information see the [Measurement Mode](#measurement-mode) section.
10
-
11
- **track_allocations** - Tracks each object location, including the object class and source file location. For more information see the [Allocation Tracking](#allocation-tracking) section.
12
-
13
- **exclude_threads** - Array of threads which should not be profiled. For more information see the [Thread Inclusion/Exclusion](#thread-inclusionexclusion) section.
14
-
15
- **include_threads** - Array of threads which should be profiled. All other threads will be ignored. For more information see the [Thread Inclusion/Exclusion](#thread-inclusionexclusion) section.
16
-
17
- **allow_exceptions** - Whether to raise exceptions encountered during profiling, or to suppress them. Defaults to false.
18
-
19
- **exclude_common** - Automatically calls `exclude_common_methods!` to exclude commonly cluttering methods. Defaults to false. For more information see the [Method Exclusion](#method-exclusion) section.
20
-
21
- ## Measurement Mode
22
-
23
- The measurement mode determines what ruby-prof measures when profiling code. Supported measurements are:
24
-
25
- ### Wall Time
26
-
27
- Wall time measures the real-world time elapsed between any two moments in seconds. 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 `QueryPerformanceCounter` and on other platforms by `clock_gettime(CLOCK_MONOTONIC)`. Use `RubyProf::WALL_TIME` to select this mode.
28
-
29
- ### Process Time
30
-
31
- Process time measures the time used by a process between any two moments in seconds. 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`. Use `RubyProf::PROCESS_TIME` to select this mode.
32
-
33
- ### Object Allocations
34
-
35
- Object allocations measures how many objects each method in a program allocates. Measurements are done via Ruby's `RUBY_INTERNAL_EVENT_NEWOBJ` trace event, counting each new object created (excluding internal `T_IMEMO` objects). Use `RubyProf::ALLOCATIONS` to select this mode.
36
-
37
- To set the measurement mode:
38
-
39
- ```ruby
40
- profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
41
- profile = RubyProf::Profile.new(measure_mode: RubyProf::PROCESS_TIME)
42
- profile = RubyProf::Profile.new(measure_mode: RubyProf::ALLOCATIONS)
43
- ```
44
-
45
- The default value is `RubyProf::WALL_TIME`. You may also specify the measure mode by using the `RUBY_PROF_MEASURE_MODE` environment variable:
46
-
47
- ```
48
- export RUBY_PROF_MEASURE_MODE=wall
49
- export RUBY_PROF_MEASURE_MODE=process
50
- export RUBY_PROF_MEASURE_MODE=allocations
51
- ```
52
-
53
- ## Allocation Tracking
54
-
55
- ruby-prof also has the ability to track object allocations. This functionality can be turned on via the track_allocations option:
56
-
57
- ```ruby
58
- require 'ruby-prof'
59
-
60
- RubyProf::Profile.profile(track_allocations: true) do
61
- ...
62
- end
63
- ```
64
-
65
- Note the `RubyProf::ALLOCATIONS` measure mode is slightly different than tracking allocations. The measurement mode provides high level information about the number of allocations performed in each method. In contrast, tracking allocations provides detailed information about allocation type, count, and source location. Currently, to see allocations results you must use the `RubyProf::GraphHtmlPrinter`.
66
-
67
- ## Thread Inclusion/Exclusion
68
-
69
- ruby-prof can profile multiple threads. Sometimes this can be overwhelming. For example, assume you want to determine why your tests are running slowly. If you are using minitest, it can run tests in parallel by spawning worker threads (to force a single worker, set `N=0` when running tests). Thus, ruby-prof provides two options to specify which threads should be profiled:
70
-
71
- **exclude_threads** - Array of threads which should not be profiled.
72
-
73
- **include_threads** - Array of threads which should be profiled. All other threads will be ignored.
74
-
75
- ## Method Exclusion
76
-
77
- ruby-prof supports excluding specific methods and threads from profiling results. This is useful for reducing connectivity in the call graph, making it easier to identify the source of performance problems when using a graph printer. For example, consider `Integer#times`: it's hardly ever useful to know how much time is spent in the method itself. We are more interested in how much the passed in block contributes to the time spent in the method which contains the `Integer#times` call. The effect on collected metrics are identical to eliminating methods from the profiling result in a post process step.
78
-
79
- ```ruby
80
- profile = RubyProf::Profile.new(...)
81
- profile.exclude_methods!(Integer, :times, ...)
82
- profile.start
83
- ```
84
-
85
- A convenience method is provided to exclude a large number of methods which usually clutter up profiles:
86
-
87
- ```ruby
88
- profile.exclude_common_methods!
89
- ```
90
-
91
- However, this is a somewhat opinionated method collection. It's usually better to view it as an inspiration instead of using it directly (see [exclude_common_methods.rb](https://github.com/ruby-prof/ruby-prof/blob/e087b7d7ca11eecf1717d95a5c5fea1e36ea3136/lib/ruby-prof/profile/exclude_common_methods.rb)).
92
-
93
- ## Merging Threads and Fibers
94
-
95
- ruby-prof profiles each thread and fiber separately. A common design pattern is to have a main thread delegate work to background threads or fibers. Examples include web servers such as Puma and Falcon, as well as code that uses `Enumerator`, `Fiber.new`, or async libraries.
96
-
97
- Understanding profiling results can be very difficult when there are many threads or fibers because each one appears as a separate entry in the output. To help with this, ruby-prof includes the ability to merge results for threads and fibers that start with the same root method. In the best case, this can collapse results into just two entries - one for the parent thread and one for all workers.
98
-
99
- Note the collapsed results show the sum of times for all merged threads/fibers. For example, assume there are 10 worker fibers that each took 5 seconds to run. The single merged entry will show a total time of 50 seconds.
100
-
101
- To merge threads and fibers:
102
-
103
- ```ruby
104
- profile = RubyProf::Profile.profile do
105
- ...
106
- end
107
- profile.merge!
108
- ```
109
-
110
- This is also supported in the Rack adapter via the `merge_fibers` option:
111
-
112
- ```ruby
113
- config.middleware.use Rack::RubyProf, path: Rails.root.join("tmp/profile"), merge_fibers: true
114
- ```
115
-
116
- ## Saving Results
117
-
118
- It can be helpful to save the results of a profiling run for later analysis. Results can be saved using Ruby's [marshal](https://docs.ruby-lang.org/en/master/Marshal.html) library.
119
-
120
- ```ruby
121
- profile_1 = RubyProf::Profile.profile do
122
- ...
123
- end
124
-
125
- # Save the results
126
- data = Marshal.dump(profile_1)
127
-
128
- # Sometime later load the results
129
- profile_2 = Marshal.load(data)
130
- ```
131
-
132
- **!!!WARNING!!!** - Only load ruby-prof profiles that you know are safe. Demarshaling data can lead to arbitrary code execution and thus can be [dangerous](https://docs.ruby-lang.org/en/master/Marshal.html#module-Marshal-label-Security+considerations).
data/docs/alternatives.md DELETED
@@ -1,98 +0,0 @@
1
- # Comparison with Other Profilers
2
-
3
- Ruby has several excellent profiling tools, each with different strengths. This page compares ruby-prof with three popular alternatives to help you choose the right tool for your needs.
4
-
5
- ## Tracing vs Sampling
6
-
7
- The most important distinction between profilers is **tracing** vs **sampling**:
8
-
9
- - **Tracing profilers** (ruby-prof) instrument every method call and return. This provides exact call counts and complete call graphs, but adds overhead to every method invocation.
10
- - **Sampling profilers** (stackprof, rbspy, vernier) periodically capture stack snapshots. This has much lower overhead but may miss short-lived method calls.
11
-
12
- ## Overview
13
-
14
- The table below compares ruby-prof with [stackprof](https://github.com/tmm1/stackprof), [rbspy](https://github.com/rbspy/rbspy), and [vernier](https://github.com/jhawthorn/vernier) — the three most popular sampling profilers for Ruby.
15
-
16
- | | ruby-prof | stackprof | rbspy | vernier |
17
- |---|---|---|---|---|
18
- | **Type** | Tracing | Sampling | Sampling | Sampling |
19
- | **Implementation** | C extension (TracePoint API) | C extension (signals) | External Rust binary | C extension (signals) |
20
- | **Code changes** | None ([CLI](getting-started.md#command-line)) or minimal | Minimal | None | Minimal |
21
- | **Ruby versions** | All, since 2006 (currently 3.2+) | 2.2+ | 1.9.3+ | 3.2.1+ |
22
- | **OS support** | Linux, macOS, Windows | Linux | Linux, macOS, Windows, FreeBSD | Linux, macOS |
23
-
24
- ## Measurement Capabilities
25
-
26
- | | ruby-prof | stackprof | rbspy | vernier |
27
- |---|---|---|---|---|
28
- | **Wall time** | Yes | Yes | Yes | Yes |
29
- | **CPU/Process time** | Yes | Yes | No | No |
30
- | **Allocations** | Yes | Yes | No | Yes |
31
- | **GVL visibility** | No | No | No | Yes |
32
- | **GC pauses** | No | No | No | Yes |
33
- | **Retained memory** | No | No | No | Yes |
34
- | **Multi-thread** | Yes | No | No | Yes |
35
- | **Fibers** | Yes | No | No | No |
36
-
37
- ## Report Formats
38
-
39
- | | ruby-prof | stackprof | rbspy | vernier |
40
- |---|---|---|---|---|
41
- | **Flat/Summary** | Yes | Yes | Yes | No |
42
- | **Call graph** | Yes (text + HTML) | No | No | No |
43
- | **Flame graph** | Yes (HTML) | Yes | Yes (SVG) | Yes (Firefox Profiler) |
44
- | **Call stack** | Yes (HTML) | No | No | No |
45
- | **Callgrind** | Yes | No | Yes | No |
46
- | **Graphviz dot** | Yes | Yes | No | No |
47
-
48
- ## When to Use Each
49
-
50
- ### ruby-prof
51
-
52
- ruby-prof is the longest-standing Ruby profiler, with its [first](./history.md) release in 2005. It has been continuously maintained for nearly two decades, evolving alongside Ruby itself from 1.8 through 4.0. Over that time it has supported every major Ruby version and platform, including Windows — a rarity among Ruby C extensions.
53
-
54
- Being a tracing profiler, ruby-prof provides *exact* information about your program. It tracks every thread, every fiber and every method call. It shines with its support for multiple measurements modes and excellent reporting capabilities.
55
-
56
- ruby-prof can be used from the [command line](getting-started.md#command-line) with no code changes, or via an API for more control.
57
-
58
- The biggest downsides of ruby-prof are:
59
-
60
- * It adds significant overhead for running programs, so is not suitable for production use
61
- * It must start a Ruby program, it cannot attach to an already running program
62
-
63
- ### stackprof
64
-
65
- [stackprof](https://github.com/tmm1/stackprof) is a low-overhead, sampling profiler that is good for development. It adds minimal overhead while still providing useful flame graphs and per-line hit counts. A good choice when you want something lightweight and well-established.
66
-
67
- The biggest downsides of stackprof are:
68
-
69
- * Single-thread only
70
- * Linux only for time-based modes
71
-
72
- ### rbspy
73
-
74
- [rbspy](https://github.com/rbspy/rbspy) is a sampling profiler best for profiling in production or when you cannot modify the application code. As an external process, it attaches to a running Ruby process by PID with zero code changes. It is particularly useful for profiling third-party Ruby applications (Chef, Puppet, etc.), investigating slow test runs, or quick profiling of scripts via `rbspy record ruby my-script.rb`. Supports the widest range of Ruby versions.
75
-
76
- The biggest downsides of rbspy are:
77
-
78
- * No allocation profiling
79
- * No call graph or caller/callee data
80
-
81
- ### vernier
82
-
83
- [vernier](https://github.com/jhawthorn/vernier) is a sampling profiler best for diagnosing concurrency issues and understanding GVL contention. It is the only Ruby profiler that reports GVL state, GC pauses and idle time. Its Firefox Profiler integration provides rich interactive visualizations with per-thread timelines.
84
-
85
- The biggest downsides of vernier are:
86
-
87
- * Requires Ruby 3.2.1+
88
- * No Windows support
89
-
90
- ### rack-mini-profiler
91
-
92
- [rack-mini-profiler](https://github.com/MiniProfiler/rack-mini-profiler) is a "batteries-included" profiling tool for Rails and Rack applications. It uses stackprof under the hood for CPU profiling while also supporting memory profiling. It is a good choice if you want an integrated profiling solution that works directly in the browser during development.
93
-
94
- ## Memory Profiling
95
-
96
- [memory_profiler](https://github.com/SamSaffron/memory_profiler) is another profiler, but it focuses exclusively on memory usage. It uses Ruby's `ObjectSpace` API to track every object allocation during a block of code, recording the source file, line number, object type, and size via `ObjectSpace.memsize_of`. By snapshotting the GC generation before and after, it distinguishes between allocated objects (created during the block) and retained objects (still alive after GC). This makes it useful for finding memory leaks and identifying allocation-heavy code. It's pure Ruby with no C extension, so it works across Ruby versions and platforms.
97
-
98
- ruby-prof can track allocation counts via its `RubyProf::ALLOCATIONS` mode, but memory_profiler gives deeper insight into memory specifically — object sizes, retained vs allocated, and per-gem breakdowns.