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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/bin/ruby-prof-check-trace +45 -45
- data/docs/advanced-usage.md +132 -132
- data/docs/best-practices.md +27 -27
- data/docs/getting-started.md +130 -130
- data/docs/index.md +45 -45
- data/docs/profiling-rails.md +64 -64
- data/docs/public/examples/generate_reports.rb +92 -92
- data/docs/public/examples/reports/call_stack.html +835 -835
- data/docs/public/examples/reports/graph.html +1319 -1319
- data/docs/reports.md +150 -150
- data/lib/ruby-prof/version.rb +1 -1
- data/ruby-prof.gemspec +66 -66
- data/test/call_tree_builder.rb +126 -126
- data/test/exceptions_test.rb +24 -24
- data/test/marshal_test.rb +144 -144
- data/test/printer_call_stack_test.rb +28 -28
- data/test/printer_flame_graph_test.rb +82 -82
- data/test/printer_flat_test.rb +99 -99
- data/test/printer_graph_html_test.rb +62 -62
- data/test/printer_graph_test.rb +42 -42
- data/test/printers_test.rb +162 -162
- data/test/printing_recursive_graph_test.rb +81 -81
- data/test/profile_test.rb +101 -101
- data/test/rack_test.rb +103 -103
- data/test/scheduler.rb +367 -367
- data/test/singleton_test.rb +39 -39
- data/test/thread_test.rb +229 -229
- data/test/yarv_test.rb +56 -56
- metadata +3 -3
data/docs/getting-started.md
CHANGED
|
@@ -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
|
-

|
|
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
|
+

|
|
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).
|
data/docs/profiling-rails.md
CHANGED
|
@@ -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:|<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:|<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
|