ruby-prof 2.0.0 → 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.
@@ -1,130 +1,130 @@
1
- # Getting Started
2
-
3
- There are three ways to use ruby-prof:
4
-
5
- - command line
6
- - convenience API
7
- - core API
8
-
9
- ## Command Line
10
-
11
- The easiest way to use ruby-prof is via the command line, which requires no modifications to your program. The basic usage is:
12
-
13
- ```
14
- ruby-prof [options] <script.rb> [--] [script-options]
15
- ```
16
-
17
- Where script.rb is the program you want to profile.
18
-
19
- For a full list of options, see the RubyProf::Cmd documentation or execute the following command:
20
-
21
- ```
22
- ruby-prof -h
23
- ```
24
-
25
- ## Convenience API
26
-
27
- The second way to use ruby-prof is via its convenience API. This requires small modifications to the program you want to profile:
28
-
29
- ```ruby
30
- require 'ruby-prof'
31
-
32
- profile = RubyProf::Profile.new
33
-
34
- # profile the code
35
- profile.start
36
- # ... code to profile ...
37
- result = profile.stop
38
-
39
- # print a flat profile to text
40
- printer = RubyProf::FlatPrinter.new(result)
41
- printer.print(STDOUT)
42
- ```
43
-
44
- Alternatively, you can use a block to tell ruby-prof what to profile:
45
-
46
- ```ruby
47
- require 'ruby-prof'
48
-
49
- # profile the code
50
- result = RubyProf::Profile.profile do
51
- # ... code to profile ...
52
- end
53
-
54
- # print a graph profile to text
55
- printer = RubyProf::GraphPrinter.new(result)
56
- printer.print(STDOUT)
57
- ```
58
-
59
- ruby-prof also supports pausing and resuming profiling runs.
60
-
61
- ```ruby
62
- require 'ruby-prof'
63
-
64
- profile = RubyProf::Profile.new
65
-
66
- # profile the code
67
- profile.start
68
- # ... code to profile ...
69
-
70
- profile.pause
71
- # ... other code ...
72
-
73
- profile.resume
74
- # ... code to profile ...
75
-
76
- result = profile.stop
77
- ```
78
-
79
- Note that resume will only work if start has been called previously. In addition, resume can also take a block:
80
-
81
- ```ruby
82
- require 'ruby-prof'
83
-
84
- profile = RubyProf::Profile.new
85
-
86
- # profile the code
87
- profile.start
88
- # ... code to profile ...
89
-
90
- profile.pause
91
- # ... other code ...
92
-
93
- profile.resume do
94
- # ... code to profile...
95
- end
96
-
97
- result = profile.stop
98
- ```
99
-
100
- With this usage, resume will automatically call pause at the end of the block.
101
-
102
- The `RubyProf::Profile.profile` method can take various options, which are described in [Profiling Options](advanced-usage.md#profiling-options).
103
-
104
- ## Core API
105
-
106
- The convenience API is a wrapper around the `RubyProf::Profile` class. Using the Profile class directly provides additional functionality, such as [method exclusion](advanced-usage.md#method-exclusion).
107
-
108
- To create a new profile:
109
-
110
- ```ruby
111
- require 'ruby-prof'
112
-
113
- profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
114
- result = profile.profile do
115
- ...
116
- end
117
- ```
118
-
119
- Once a profile is completed, you can either generate a [report](reports.md) via a printer or [save](advanced-usage.md#saving-results) the results for later analysis. For a list of profiling options, please see the [Profiling Options](advanced-usage.md#profiling-options) section.
120
- If you are unsure which report to generate first, see [Report Types](reports.md#report-types).
121
-
122
-
123
- However, using ruby-prof also comes with two caveats:
124
-
125
- - To use ruby-prof you generally need to include a few lines of extra code in your program (although see [command line usage](getting-started.md#command-line))
126
- - Using ruby-prof will cause your program to run slower (see [Performance](index.md#performance) section)
127
-
128
- Most of the time, these two caveats are acceptable. But if you need to determine why a program running in production is slow or hung, a sampling profiler will be a better choice. Excellent choices include [stackprof](https://github.com/tmm1/stackprof) or [rbspy](https://rbspy.github.io/).
129
-
130
- If you are just interested in memory usage, you may also want to checkout the [memory_profiler](https://github.com/SamSaffron/memory_profiler) gem (although ruby-prof provides similar information).
1
+ # Getting Started
2
+
3
+ There are three ways to use ruby-prof:
4
+
5
+ - command line
6
+ - convenience API
7
+ - core API
8
+
9
+ ## Command Line
10
+
11
+ The easiest way to use ruby-prof is via the command line, which requires no modifications to your program. The basic usage is:
12
+
13
+ ```
14
+ ruby-prof [options] <script.rb> [--] [script-options]
15
+ ```
16
+
17
+ Where script.rb is the program you want to profile.
18
+
19
+ For a full list of options, see the RubyProf::Cmd documentation or execute the following command:
20
+
21
+ ```
22
+ ruby-prof -h
23
+ ```
24
+
25
+ ## Convenience API
26
+
27
+ The second way to use ruby-prof is via its convenience API. This requires small modifications to the program you want to profile:
28
+
29
+ ```ruby
30
+ require 'ruby-prof'
31
+
32
+ profile = RubyProf::Profile.new
33
+
34
+ # profile the code
35
+ profile.start
36
+ # ... code to profile ...
37
+ result = profile.stop
38
+
39
+ # print a flat profile to text
40
+ printer = RubyProf::FlatPrinter.new(result)
41
+ printer.print(STDOUT)
42
+ ```
43
+
44
+ Alternatively, you can use a block to tell ruby-prof what to profile:
45
+
46
+ ```ruby
47
+ require 'ruby-prof'
48
+
49
+ # profile the code
50
+ result = RubyProf::Profile.profile do
51
+ # ... code to profile ...
52
+ end
53
+
54
+ # print a graph profile to text
55
+ printer = RubyProf::GraphPrinter.new(result)
56
+ printer.print(STDOUT)
57
+ ```
58
+
59
+ ruby-prof also supports pausing and resuming profiling runs.
60
+
61
+ ```ruby
62
+ require 'ruby-prof'
63
+
64
+ profile = RubyProf::Profile.new
65
+
66
+ # profile the code
67
+ profile.start
68
+ # ... code to profile ...
69
+
70
+ profile.pause
71
+ # ... other code ...
72
+
73
+ profile.resume
74
+ # ... code to profile ...
75
+
76
+ result = profile.stop
77
+ ```
78
+
79
+ Note that resume will only work if start has been called previously. In addition, resume can also take a block:
80
+
81
+ ```ruby
82
+ require 'ruby-prof'
83
+
84
+ profile = RubyProf::Profile.new
85
+
86
+ # profile the code
87
+ profile.start
88
+ # ... code to profile ...
89
+
90
+ profile.pause
91
+ # ... other code ...
92
+
93
+ profile.resume do
94
+ # ... code to profile...
95
+ end
96
+
97
+ result = profile.stop
98
+ ```
99
+
100
+ With this usage, resume will automatically call pause at the end of the block.
101
+
102
+ The `RubyProf::Profile.profile` method can take various options, which are described in [Profiling Options](advanced-usage.md#profiling-options).
103
+
104
+ ## Core API
105
+
106
+ The convenience API is a wrapper around the `RubyProf::Profile` class. Using the Profile class directly provides additional functionality, such as [method exclusion](advanced-usage.md#method-exclusion).
107
+
108
+ To create a new profile:
109
+
110
+ ```ruby
111
+ require 'ruby-prof'
112
+
113
+ profile = RubyProf::Profile.new(measure_mode: RubyProf::WALL_TIME)
114
+ result = profile.profile do
115
+ ...
116
+ end
117
+ ```
118
+
119
+ Once a profile is completed, you can either generate a [report](reports.md) via a printer or [save](advanced-usage.md#saving-results) the results for later analysis. For a list of profiling options, please see the [Profiling Options](advanced-usage.md#profiling-options) section.
120
+ If you are unsure which report to generate first, see [Report Types](reports.md#report-types).
121
+
122
+
123
+ However, using ruby-prof also comes with two caveats:
124
+
125
+ - To use ruby-prof you generally need to include a few lines of extra code in your program (although see [command line usage](getting-started.md#command-line))
126
+ - Using ruby-prof will cause your program to run slower (see [Performance](index.md#performance) section)
127
+
128
+ Most of the time, these two caveats are acceptable. But if you need to determine why a program running in production is slow or hung, a sampling profiler will be a better choice. Excellent choices include [stackprof](https://github.com/tmm1/stackprof) or [rbspy](https://rbspy.github.io/).
129
+
130
+ If you are just interested in memory usage, you may also want to checkout the [memory_profiler](https://github.com/SamSaffron/memory_profiler) gem (although ruby-prof provides similar information).
data/docs/index.md CHANGED
@@ -1,45 +1,45 @@
1
- # ruby-prof
2
-
3
- ruby-prof is a [tracing](./alternatives.md#tracing-vs-sampling) profiler for MRI Ruby with a long [history](./history.md) that dates back to 2005! Its features include:
4
-
5
- - Measurement Modes - ruby-prof can measure program [wall time](advanced-usage.md#wall-time), [process time](advanced-usage.md#process-time) and [object allocations](advanced-usage.md#object-allocations).
6
- - Reports - ruby-prof can generate [flat](reports.md#flat), [graph (text)](reports.md#graph-text), [graph (HTML)](reports.md#graph-html), [flame graph](reports.md#flame-graph), [call stack](reports.md#call-stack), [graphviz](reports.md#graphviz), [cachegrind](reports.md#cachegrind), and [call info](reports.md#call-info-report) reports.
7
- - Threads - supports profiling multiple threads simultaneously.
8
- - Fibers - supports profiling multiple fibers simultaneously.
9
- - Merging - supports merging results across fibers or threads
10
- - Recursive - supports profiling recursive methods
11
-
12
- ![Flame Graph](../public/images/flame_graph.png)
13
-
14
- ## Why ruby-prof?
15
-
16
- ruby-prof is helpful if your program is slow and you want to know why! It can help you track down methods that are either slow or allocate a large number of objects. Often times the results will surprise you - when profiling what you think you know almost always turns out to be wrong.
17
-
18
- ## Installation
19
- To install ruby-prof:
20
-
21
- ```
22
- gem install ruby-prof
23
- ```
24
-
25
- If you are running Linux or Unix you'll need to have a C compiler installed so the extension can be built when it is installed. If you are running Windows, then you should install the Windows specific gem or install [devkit](https://rubyinstaller.org/add-ons/devkit.html).
26
-
27
- ruby-prof requires Ruby 3.2.0 or higher. If you need to work with older Ruby versions then you can download an older version of ruby-prof.
28
-
29
- ## Performance
30
- ruby-prof is a tracing profiler, not a sampling profiler, and thus will cause your program to run slower. Our tests show that the overhead varies considerably based on the code being profiled. Significant effort has been put into reducing this overhead, but most programs will run approximately twice as slow while highly recursive programs (like the fibonacci series test) may run up to five times slower.
31
-
32
- ## History
33
- ruby-prof has been under continuous development since 2005 — see the full [History](history.md) page.
34
-
35
- ## API Documentation
36
-
37
- API documentation for each class is available at the [ruby-prof API docs](https://ruby-prof.github.io/doc/index.html).
38
-
39
- ## License
40
-
41
- See [LICENSE](../LICENSE) for license information.
42
-
43
- ## Development
44
-
45
- Code is located at [github.com/ruby-prof/ruby-prof](https://github.com/ruby-prof/ruby-prof).
1
+ # ruby-prof
2
+
3
+ ruby-prof is a [tracing](./alternatives.md#tracing-vs-sampling) profiler for MRI Ruby with a long [history](./history.md) that dates back to 2005! Its features include:
4
+
5
+ - Measurement Modes - ruby-prof can measure program [wall time](advanced-usage.md#wall-time), [process time](advanced-usage.md#process-time) and [object allocations](advanced-usage.md#object-allocations).
6
+ - Reports - ruby-prof can generate [flat](reports.md#flat), [graph (text)](reports.md#graph-text), [graph (HTML)](reports.md#graph-html), [flame graph](reports.md#flame-graph), [call stack](reports.md#call-stack), [graphviz](reports.md#graphviz), [cachegrind](reports.md#cachegrind), and [call info](reports.md#call-info-report) reports.
7
+ - Threads - supports profiling multiple threads simultaneously.
8
+ - Fibers - supports profiling multiple fibers simultaneously.
9
+ - Merging - supports merging results across fibers or threads
10
+ - Recursive - supports profiling recursive methods
11
+
12
+ ![Flame Graph](../public/images/flame_graph.png)
13
+
14
+ ## Why ruby-prof?
15
+
16
+ ruby-prof is helpful if your program is slow and you want to know why! It can help you track down methods that are either slow or allocate a large number of objects. Often times the results will surprise you - when profiling what you think you know almost always turns out to be wrong.
17
+
18
+ ## Installation
19
+ To install ruby-prof:
20
+
21
+ ```
22
+ gem install ruby-prof
23
+ ```
24
+
25
+ If you are running Linux or Unix you'll need to have a C compiler installed so the extension can be built when it is installed. If you are running Windows, then you should install the Windows specific gem or install [devkit](https://rubyinstaller.org/add-ons/devkit.html).
26
+
27
+ ruby-prof requires Ruby 3.2.0 or higher. If you need to work with older Ruby versions then you can download an older version of ruby-prof.
28
+
29
+ ## Performance
30
+ ruby-prof is a tracing profiler, not a sampling profiler, and thus will cause your program to run slower. Our tests show that the overhead varies considerably based on the code being profiled. Significant effort has been put into reducing this overhead, but most programs will run approximately twice as slow while highly recursive programs (like the fibonacci series test) may run up to five times slower.
31
+
32
+ ## History
33
+ ruby-prof has been under continuous development since 2005 — see the full [History](history.md) page.
34
+
35
+ ## API Documentation
36
+
37
+ API documentation for each class is available at the [ruby-prof API docs](https://ruby-prof.github.io/doc/index.html).
38
+
39
+ ## License
40
+
41
+ See [LICENSE](../LICENSE) for license information.
42
+
43
+ ## Development
44
+
45
+ Code is located at [github.com/ruby-prof/ruby-prof](https://github.com/ruby-prof/ruby-prof).
@@ -1,64 +1,64 @@
1
- # Profiling Rails
2
-
3
- To profile a Rails application it is vital to run it using production-like settings (cache classes, cache view lookups, etc.). Otherwise, Rails dependency loading code will overwhelm any time spent in the application itself (our tests show that Rails dependency loading causes a roughly 6x slowdown). The best way to do this is to create a new Rails environment, `profile`.
4
-
5
- To profile Rails:
6
-
7
- 1. Add ruby-prof to your Gemfile:
8
-
9
- ```ruby
10
- group :profile do
11
- gem 'ruby-prof'
12
- end
13
- ```
14
-
15
- Then install it:
16
-
17
- ```bash
18
- bundle install
19
- ```
20
-
21
- 2. Create `config/environments/profile.rb` with production-like settings and the ruby-prof middleware:
22
-
23
- ```ruby
24
- # config/environments/profile.rb
25
- require_relative "production"
26
-
27
- Rails.application.configure do
28
- # Optional: reduce noise while profiling.
29
- config.log_level = :warn
30
-
31
- # Optional: disable controller/view caching if you want raw app execution timing.
32
- config.action_controller.perform_caching = false
33
-
34
- config.middleware.use Rack::RubyProf, path: Rails.root.join("tmp/profile")
35
- end
36
- ```
37
-
38
- By default the rack adapter generates flat text, graph text, graph HTML, and call stack HTML reports.
39
-
40
- 3. Start Rails in the profile environment:
41
-
42
- ```bash
43
- bin/rails server -e profile
44
- ```
45
-
46
- You can run a console in the same environment with:
47
-
48
- ```bash
49
- bin/rails console -e profile
50
- ```
51
-
52
- 4. Make a request to generate profile output:
53
-
54
- ```bash
55
- curl http://127.0.0.1:3000/
56
- ```
57
-
58
- 5. Inspect reports in `tmp/profile`:
59
-
60
- ```bash
61
- ls -1 tmp/profile
62
- ```
63
-
64
- Reports are generated per request path. Repeating the same request path overwrites the previous report files for that path.
1
+ # Profiling Rails
2
+
3
+ To profile a Rails application it is vital to run it using production-like settings (cache classes, cache view lookups, etc.). Otherwise, Rails dependency loading code will overwhelm any time spent in the application itself (our tests show that Rails dependency loading causes a roughly 6x slowdown). The best way to do this is to create a new Rails environment, `profile`.
4
+
5
+ To profile Rails:
6
+
7
+ 1. Add ruby-prof to your Gemfile:
8
+
9
+ ```ruby
10
+ group :profile do
11
+ gem 'ruby-prof'
12
+ end
13
+ ```
14
+
15
+ Then install it:
16
+
17
+ ```bash
18
+ bundle install
19
+ ```
20
+
21
+ 2. Create `config/environments/profile.rb` with production-like settings and the ruby-prof middleware:
22
+
23
+ ```ruby
24
+ # config/environments/profile.rb
25
+ require_relative "production"
26
+
27
+ Rails.application.configure do
28
+ # Optional: reduce noise while profiling.
29
+ config.log_level = :warn
30
+
31
+ # Optional: disable controller/view caching if you want raw app execution timing.
32
+ config.action_controller.perform_caching = false
33
+
34
+ config.middleware.use Rack::RubyProf, path: Rails.root.join("tmp/profile")
35
+ end
36
+ ```
37
+
38
+ By default the rack adapter generates flat text, graph text, graph HTML, and call stack HTML reports.
39
+
40
+ 3. Start Rails in the profile environment:
41
+
42
+ ```bash
43
+ bin/rails server -e profile
44
+ ```
45
+
46
+ You can run a console in the same environment with:
47
+
48
+ ```bash
49
+ bin/rails console -e profile
50
+ ```
51
+
52
+ 4. Make a request to generate profile output:
53
+
54
+ ```bash
55
+ curl http://127.0.0.1:3000/
56
+ ```
57
+
58
+ 5. Inspect reports in `tmp/profile`:
59
+
60
+ ```bash
61
+ ls -1 tmp/profile
62
+ ```
63
+
64
+ Reports are generated per request path. Repeating the same request path overwrites the previous report files for that path.
@@ -1,92 +1,92 @@
1
- #!/usr/bin/env ruby
2
- # encoding: UTF-8
3
-
4
- # Generates example reports for all ruby-prof printers.
5
- # Usage: ruby docs/public/examples/generate_reports.rb
6
-
7
- # To make testing/debugging easier test within this source tree versus an installed gem
8
- require 'bundler/setup'
9
-
10
- # Add ext directory to load path to make it easier to test locally built extensions
11
- ext_path = File.expand_path(File.join(__dir__, '..', '..', '..', 'ext', 'ruby_prof'))
12
- $LOAD_PATH.unshift(ext_path)
13
-
14
- require 'fileutils'
15
- require 'stringio'
16
- require 'uri'
17
- require 'ruby-prof'
18
- require_relative 'example'
19
-
20
- output_dir = File.join(File.dirname(__FILE__), "reports")
21
- FileUtils.mkdir_p(output_dir)
22
-
23
- def sanitize_local_file_links(path)
24
- content = File.read(path)
25
- content.gsub!(%r{href="file://[^"]*/docs/public/examples/([^"#]+)#\d+"}, 'href="../\1"')
26
- content.gsub!(%r{title=".*?/docs/public/examples/([^":]+):\d+"}, 'title="\1"')
27
- content.gsub!(%r{href="file://[^"]+"}, 'href="#"')
28
- content.gsub!(%r{title="[^"]*(?:<internal:|&lt;internal:)[^"]+"}, 'title="internal"')
29
- File.write(path, content)
30
- end
31
-
32
- result = RubyProf::Profile.profile(measure_mode: RubyProf::WALL_TIME) do
33
- run_example
34
- end
35
-
36
- # Flame Graph
37
- File.open(File.join(output_dir, "flame_graph.html"), "wb") do |f|
38
- RubyProf::FlameGraphPrinter.new(result).print(f)
39
- end
40
-
41
- # Call Stack
42
- File.open(File.join(output_dir, "call_stack.html"), "wb") do |f|
43
- RubyProf::CallStackPrinter.new(result).print(f)
44
- end
45
- sanitize_local_file_links(File.join(output_dir, "call_stack.html"))
46
-
47
- # Graph HTML
48
- File.open(File.join(output_dir, "graph.html"), "wb") do |f|
49
- RubyProf::GraphHtmlPrinter.new(result).print(f)
50
- end
51
- sanitize_local_file_links(File.join(output_dir, "graph.html"))
52
-
53
- # Graph (text)
54
- File.open(File.join(output_dir, "graph.txt"), "wb") do |f|
55
- RubyProf::GraphPrinter.new(result).print(f)
56
- end
57
-
58
- # Flat
59
- File.open(File.join(output_dir, "flat.txt"), "wb") do |f|
60
- RubyProf::FlatPrinter.new(result).print(f)
61
- end
62
-
63
- # Call Info
64
- File.open(File.join(output_dir, "call_info.txt"), "wb") do |f|
65
- RubyProf::CallInfoPrinter.new(result).print(f)
66
- end
67
-
68
- # Dot
69
- dot_io = StringIO.new
70
- RubyProf::DotPrinter.new(result).print(dot_io)
71
- dot_content = dot_io.string
72
- File.open(File.join(output_dir, "graph.dot"), "wb") do |f|
73
- f << dot_content
74
- end
75
-
76
- # Graphviz Online viewer with dot content embedded in URL
77
- viewer_url = "https://dreampuf.github.io/GraphvizOnline/?engine=dot#" + URI.encode_uri_component(dot_content)
78
- File.open(File.join(output_dir, "graphviz_viewer.html"), "wb") do |f|
79
- f << %(<html><head><meta http-equiv="refresh" content="0;url=#{viewer_url}"></head></html>)
80
- end
81
-
82
- # Call Tree (calltree format)
83
- RubyProf::CallTreePrinter.new(result).print(path: output_dir, profile: "profile")
84
- # Rename PID-based filename to a stable name
85
- Dir.glob(File.join(output_dir, "callgrind.out.*")).each do |f|
86
- FileUtils.mv(f, File.join(output_dir, "callgrind.out"))
87
- end
88
-
89
- puts "Reports written to #{output_dir}/"
90
- Dir.glob(File.join(output_dir, "*")).sort.each do |f|
91
- puts " #{File.basename(f)}"
92
- end
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ # Generates example reports for all ruby-prof printers.
5
+ # Usage: ruby docs/public/examples/generate_reports.rb
6
+
7
+ # To make testing/debugging easier test within this source tree versus an installed gem
8
+ require 'bundler/setup'
9
+
10
+ # Add ext directory to load path to make it easier to test locally built extensions
11
+ ext_path = File.expand_path(File.join(__dir__, '..', '..', '..', 'ext', 'ruby_prof'))
12
+ $LOAD_PATH.unshift(ext_path)
13
+
14
+ require 'fileutils'
15
+ require 'stringio'
16
+ require 'uri'
17
+ require 'ruby-prof'
18
+ require_relative 'example'
19
+
20
+ output_dir = File.join(File.dirname(__FILE__), "reports")
21
+ FileUtils.mkdir_p(output_dir)
22
+
23
+ def sanitize_local_file_links(path)
24
+ content = File.read(path)
25
+ content.gsub!(%r{href="file://[^"]*/docs/public/examples/([^"#]+)#\d+"}, 'href="../\1"')
26
+ content.gsub!(%r{title=".*?/docs/public/examples/([^":]+):\d+"}, 'title="\1"')
27
+ content.gsub!(%r{href="file://[^"]+"}, 'href="#"')
28
+ content.gsub!(%r{title="[^"]*(?:<internal:|&lt;internal:)[^"]+"}, 'title="internal"')
29
+ File.write(path, content)
30
+ end
31
+
32
+ result = RubyProf::Profile.profile(measure_mode: RubyProf::WALL_TIME) do
33
+ run_example
34
+ end
35
+
36
+ # Flame Graph
37
+ File.open(File.join(output_dir, "flame_graph.html"), "wb") do |f|
38
+ RubyProf::FlameGraphPrinter.new(result).print(f)
39
+ end
40
+
41
+ # Call Stack
42
+ File.open(File.join(output_dir, "call_stack.html"), "wb") do |f|
43
+ RubyProf::CallStackPrinter.new(result).print(f)
44
+ end
45
+ sanitize_local_file_links(File.join(output_dir, "call_stack.html"))
46
+
47
+ # Graph HTML
48
+ File.open(File.join(output_dir, "graph.html"), "wb") do |f|
49
+ RubyProf::GraphHtmlPrinter.new(result).print(f)
50
+ end
51
+ sanitize_local_file_links(File.join(output_dir, "graph.html"))
52
+
53
+ # Graph (text)
54
+ File.open(File.join(output_dir, "graph.txt"), "wb") do |f|
55
+ RubyProf::GraphPrinter.new(result).print(f)
56
+ end
57
+
58
+ # Flat
59
+ File.open(File.join(output_dir, "flat.txt"), "wb") do |f|
60
+ RubyProf::FlatPrinter.new(result).print(f)
61
+ end
62
+
63
+ # Call Info
64
+ File.open(File.join(output_dir, "call_info.txt"), "wb") do |f|
65
+ RubyProf::CallInfoPrinter.new(result).print(f)
66
+ end
67
+
68
+ # Dot
69
+ dot_io = StringIO.new
70
+ RubyProf::DotPrinter.new(result).print(dot_io)
71
+ dot_content = dot_io.string
72
+ File.open(File.join(output_dir, "graph.dot"), "wb") do |f|
73
+ f << dot_content
74
+ end
75
+
76
+ # Graphviz Online viewer with dot content embedded in URL
77
+ viewer_url = "https://dreampuf.github.io/GraphvizOnline/?engine=dot#" + URI.encode_uri_component(dot_content)
78
+ File.open(File.join(output_dir, "graphviz_viewer.html"), "wb") do |f|
79
+ f << %(<html><head><meta http-equiv="refresh" content="0;url=#{viewer_url}"></head></html>)
80
+ end
81
+
82
+ # Call Tree (calltree format)
83
+ RubyProf::CallTreePrinter.new(result).print(path: output_dir, profile: "profile")
84
+ # Rename PID-based filename to a stable name
85
+ Dir.glob(File.join(output_dir, "callgrind.out.*")).each do |f|
86
+ FileUtils.mv(f, File.join(output_dir, "callgrind.out"))
87
+ end
88
+
89
+ puts "Reports written to #{output_dir}/"
90
+ Dir.glob(File.join(output_dir, "*")).sort.each do |f|
91
+ puts " #{File.basename(f)}"
92
+ end