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.
- checksums.yaml +4 -4
- data/{CHANGES → CHANGELOG.md} +118 -176
- data/README.md +5 -5
- data/bin/ruby-prof +1 -4
- data/docs/advanced-usage.md +132 -0
- data/docs/alternatives.md +98 -0
- data/docs/architecture.md +122 -0
- data/docs/best-practices.md +27 -0
- data/docs/getting-started.md +130 -0
- data/docs/history.md +11 -0
- data/docs/index.md +45 -0
- data/docs/profiling-rails.md +64 -0
- data/docs/public/examples/example.rb +33 -0
- data/docs/public/examples/generate_reports.rb +92 -0
- data/docs/public/examples/reports/call_info.txt +27 -0
- data/docs/public/examples/reports/call_stack.html +835 -0
- data/docs/public/examples/reports/callgrind.out +150 -0
- data/docs/public/examples/reports/flame_graph.html +408 -0
- data/docs/public/examples/reports/flat.txt +45 -0
- data/docs/public/examples/reports/graph.dot +129 -0
- data/docs/public/examples/reports/graph.html +1319 -0
- data/docs/public/examples/reports/graph.txt +100 -0
- data/docs/public/examples/reports/graphviz_viewer.html +1 -0
- data/docs/public/images/call_stack.png +0 -0
- data/docs/public/images/class_diagram.png +0 -0
- data/docs/public/images/dot_printer.png +0 -0
- data/docs/public/images/flame_graph.png +0 -0
- data/docs/public/images/flat.png +0 -0
- data/docs/public/images/graph.png +0 -0
- data/docs/public/images/graph_html.png +0 -0
- data/docs/public/images/ruby-prof-logo.svg +1 -0
- data/docs/reports.md +150 -0
- data/docs/stylesheets/extra.css +80 -0
- data/ext/ruby_prof/extconf.rb +23 -22
- data/ext/ruby_prof/rp_allocation.c +0 -15
- data/ext/ruby_prof/rp_allocation.h +29 -33
- data/ext/ruby_prof/rp_call_tree.c +3 -0
- data/ext/ruby_prof/rp_call_tree.h +1 -4
- data/ext/ruby_prof/rp_call_trees.c +296 -296
- data/ext/ruby_prof/rp_call_trees.h +25 -28
- data/ext/ruby_prof/rp_measure_allocations.c +47 -47
- data/ext/ruby_prof/rp_measure_process_time.c +64 -66
- data/ext/ruby_prof/rp_measure_wall_time.c +52 -64
- data/ext/ruby_prof/rp_measurement.c +0 -5
- data/ext/ruby_prof/rp_measurement.h +49 -53
- data/ext/ruby_prof/rp_method.c +554 -551
- data/ext/ruby_prof/rp_method.h +1 -4
- data/ext/ruby_prof/rp_profile.c +1 -1
- data/ext/ruby_prof/rp_profile.h +1 -5
- data/ext/ruby_prof/rp_stack.c +212 -212
- data/ext/ruby_prof/rp_stack.h +50 -53
- data/ext/ruby_prof/rp_thread.h +1 -4
- data/ext/ruby_prof/ruby_prof.c +50 -50
- data/ext/ruby_prof/ruby_prof.h +4 -6
- data/ext/ruby_prof/vc/ruby_prof.vcxproj +7 -8
- data/lib/ruby-prof/assets/call_stack_printer.html.erb +746 -711
- data/lib/ruby-prof/assets/flame_graph_printer.html.erb +412 -0
- data/lib/ruby-prof/assets/graph_printer.html.erb +355 -355
- data/lib/ruby-prof/call_tree.rb +57 -57
- data/lib/ruby-prof/call_tree_visitor.rb +36 -36
- data/lib/ruby-prof/exclude_common_methods.rb +204 -204
- data/lib/ruby-prof/measurement.rb +17 -17
- data/lib/ruby-prof/printers/abstract_printer.rb +142 -138
- data/lib/ruby-prof/printers/call_info_printer.rb +53 -53
- data/lib/ruby-prof/printers/call_stack_printer.rb +168 -180
- data/lib/ruby-prof/printers/call_tree_printer.rb +132 -145
- data/lib/ruby-prof/printers/dot_printer.rb +177 -132
- data/lib/ruby-prof/printers/flame_graph_printer.rb +79 -0
- data/lib/ruby-prof/printers/flat_printer.rb +52 -52
- data/lib/ruby-prof/printers/graph_html_printer.rb +62 -63
- data/lib/ruby-prof/printers/graph_printer.rb +112 -113
- data/lib/ruby-prof/printers/multi_printer.rb +134 -127
- data/lib/ruby-prof/profile.rb +13 -0
- data/lib/ruby-prof/rack.rb +114 -105
- data/lib/ruby-prof/task.rb +147 -147
- data/lib/ruby-prof/thread.rb +20 -20
- data/lib/ruby-prof/version.rb +3 -3
- data/lib/ruby-prof.rb +50 -52
- data/lib/unprof.rb +10 -10
- data/ruby-prof.gemspec +66 -65
- data/test/abstract_printer_test.rb +25 -27
- data/test/alias_test.rb +203 -117
- data/test/call_tree_builder.rb +126 -126
- data/test/call_tree_visitor_test.rb +27 -27
- data/test/call_trees_test.rb +66 -66
- data/test/duplicate_names_test.rb +32 -32
- data/test/dynamic_method_test.rb +50 -62
- data/test/enumerable_test.rb +23 -21
- data/test/exceptions_test.rb +24 -24
- data/test/exclude_methods_test.rb +363 -257
- data/test/exclude_threads_test.rb +48 -48
- data/test/fiber_test.rb +195 -195
- data/test/gc_test.rb +104 -102
- data/test/inverse_call_tree_test.rb +174 -174
- data/test/line_number_test.rb +563 -289
- data/test/marshal_test.rb +144 -145
- data/test/measure_allocations.rb +26 -26
- data/test/measure_allocations_test.rb +1511 -1081
- data/test/measure_process_time_test.rb +3286 -2477
- data/test/measure_times.rb +56 -56
- data/test/measure_wall_time_test.rb +773 -568
- data/test/measurement_test.rb +82 -82
- data/test/merge_test.rb +146 -146
- data/test/method_info_test.rb +100 -95
- data/test/multi_printer_test.rb +52 -66
- data/test/no_method_class_test.rb +15 -15
- data/test/pause_resume_test.rb +171 -171
- data/test/prime.rb +54 -54
- data/test/prime_script.rb +5 -5
- data/test/printer_call_stack_test.rb +28 -27
- data/test/printer_call_tree_test.rb +30 -30
- data/test/printer_flame_graph_test.rb +82 -0
- data/test/printer_flat_test.rb +99 -99
- data/test/printer_graph_html_test.rb +62 -59
- data/test/printer_graph_test.rb +42 -40
- data/test/printers_test.rb +162 -135
- data/test/printing_recursive_graph_test.rb +81 -81
- data/test/profile_test.rb +101 -101
- data/test/rack_test.rb +103 -93
- data/test/recursive_test.rb +796 -622
- data/test/scheduler.rb +4 -0
- data/test/singleton_test.rb +39 -38
- data/test/stack_printer_test.rb +61 -61
- data/test/start_stop_test.rb +106 -106
- data/test/test_helper.rb +24 -20
- data/test/thread_test.rb +229 -231
- data/test/unique_call_path_test.rb +123 -136
- data/test/yarv_test.rb +56 -60
- metadata +68 -16
- data/ext/ruby_prof/rp_measure_memory.c +0 -46
- data/lib/ruby-prof/compatibility.rb +0 -113
- data/test/compatibility_test.rb +0 -49
- data/test/crash2.rb +0 -144
- 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
|
data/test/compatibility_test.rb
DELETED
|
@@ -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
|