ruby-prof 1.3.1 → 1.3.2
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 +5 -0
- data/Rakefile +2 -3
- data/lib/ruby-prof.rb +3 -2
- data/lib/ruby-prof/rack.rb +51 -130
- data/lib/ruby-prof/version.rb +1 -1
- data/test/rack_test.rb +0 -64
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9dbafd0a6aebb3d09c5f7f198d4261fbd39709c33ec216ea542e8fe2063cd2b9
|
4
|
+
data.tar.gz: f66379b3e8b2c5fde1ef01ce84484a6b9f958bb643c4783e32fd6b37f033efb0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 134cb10903895675ccfa34ab880ecdcd04bf55d8b749fff2f431655777b1801820e0a68c5b402d5200beb0c2e942d5833cac6a2faaa897a9be36c5b2531e30d2
|
7
|
+
data.tar.gz: '09400b5f8f70abb628984dff8cd270bfb490db686f06d89530ee25a68c9e5cf7546da429ca48570cfa57e73af092ca38964fa64fb30e3b987a1fa1503b212047'
|
data/CHANGES
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
1.3.2 (2020-04-19)
|
2
|
+
=====================
|
3
|
+
* Fix rack profiler so it is thread safe (Charlie Savage)
|
4
|
+
* Fix loading of prebuilt binaries on mingw64 to use Ruby's major and minor version (Charlie Savage)
|
5
|
+
|
1
6
|
1.3.1 (2020-03-11)
|
2
7
|
=====================
|
3
8
|
* Add max_percent and filter_by options to flat printer (Sean McGivern)
|
data/Rakefile
CHANGED
@@ -38,9 +38,9 @@ Rake::ExtensionTask.new do |ext|
|
|
38
38
|
ext.gem_spec = default_spec
|
39
39
|
ext.name = SO_NAME
|
40
40
|
ext.ext_dir = "ext/#{SO_NAME}"
|
41
|
-
ext.lib_dir = "lib/#{RUBY_VERSION}"
|
41
|
+
ext.lib_dir = "lib/#{Gem::Version.new(RUBY_VERSION).segments[0..1].join('.')}"
|
42
42
|
ext.cross_compile = true
|
43
|
-
ext.cross_platform = ['
|
43
|
+
ext.cross_platform = ['x64-mingw32']
|
44
44
|
end
|
45
45
|
|
46
46
|
# Rake task to build the default package
|
@@ -58,7 +58,6 @@ if RUBY_PLATFORM.match(/win32|mingw32/)
|
|
58
58
|
win_spec = default_spec.clone
|
59
59
|
win_spec.platform = Gem::Platform::CURRENT
|
60
60
|
win_spec.files += Dir.glob('lib/**/*.so')
|
61
|
-
win_spec.instance_variable_set(:@cache_file, nil) # Hack to work around gem issue
|
62
61
|
|
63
62
|
# Unset extensions
|
64
63
|
win_spec.extensions = nil
|
data/lib/ruby-prof.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
require 'rubygems/version'
|
2
3
|
|
3
4
|
# Load the C-based binding.
|
4
5
|
begin
|
5
|
-
|
6
|
-
require "#{
|
6
|
+
version = Gem::Version.new(RUBY_VERSION)
|
7
|
+
require "#{version.segments[0..1].join('.')}/ruby_prof.so"
|
7
8
|
rescue LoadError
|
8
9
|
require "ruby_prof.so"
|
9
10
|
end
|
data/lib/ruby-prof/rack.rb
CHANGED
@@ -5,43 +5,37 @@ module Rack
|
|
5
5
|
class RubyProf
|
6
6
|
def initialize(app, options = {})
|
7
7
|
@app = app
|
8
|
+
@options = options
|
9
|
+
@options[:min_percent] ||= 1
|
8
10
|
|
9
|
-
options[:
|
11
|
+
@tmpdir = options[:path] || Dir.tmpdir
|
12
|
+
FileUtils.mkdir_p(@tmpdir)
|
10
13
|
|
11
|
-
options[:
|
12
|
-
|
14
|
+
@printer_klasses = @options[:printers] || {::RubyProf::FlatPrinter => 'flat.txt',
|
15
|
+
::RubyProf::GraphPrinter => 'graph.txt',
|
16
|
+
::RubyProf::GraphHtmlPrinter => 'graph.html',
|
17
|
+
::RubyProf::CallStackPrinter => 'call_stack.html'}
|
13
18
|
|
14
19
|
@skip_paths = options[:skip_paths] || [%r{^/assets}, %r{\.(css|js|png|jpeg|jpg|gif)$}]
|
15
20
|
@only_paths = options[:only_paths]
|
16
|
-
|
17
|
-
@max_requests = options[:max_requests]
|
18
|
-
|
19
|
-
@options = options
|
20
21
|
end
|
21
22
|
|
22
23
|
def call(env)
|
23
24
|
request = Rack::Request.new(env)
|
24
25
|
|
25
26
|
if should_profile?(request.path)
|
26
|
-
profiler.resume
|
27
27
|
begin
|
28
|
-
result =
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
result = nil
|
29
|
+
data = ::RubyProf::Profile.profile(profiling_options) do
|
30
|
+
result = @app.call(env)
|
31
|
+
end
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
nil
|
36
|
-
else
|
37
|
-
request.path.gsub('/', '-')[1..-1]
|
38
|
-
end
|
33
|
+
path = request.path.gsub('/', '-')
|
34
|
+
path.slice!(0)
|
39
35
|
|
40
|
-
|
41
|
-
|
36
|
+
print(data, path)
|
37
|
+
result
|
42
38
|
end
|
43
|
-
|
44
|
-
result
|
45
39
|
else
|
46
40
|
@app.call(env)
|
47
41
|
end
|
@@ -49,126 +43,53 @@ module Rack
|
|
49
43
|
|
50
44
|
private
|
51
45
|
|
52
|
-
|
53
|
-
|
54
|
-
@options = options
|
55
|
-
|
56
|
-
@profile = ::RubyProf::Profile.new(profiling_options)
|
57
|
-
@profile.start
|
58
|
-
@profile.pause
|
59
|
-
|
60
|
-
@printer_klasses = options[:printers] || default_printers
|
61
|
-
|
62
|
-
@tmpdir = options[:path]
|
63
|
-
|
64
|
-
@max_requests = options[:max_requests] || 1
|
65
|
-
@requests_count = 0
|
46
|
+
def should_profile?(path)
|
47
|
+
return false if paths_match?(path, @skip_paths)
|
66
48
|
|
67
|
-
|
68
|
-
|
69
|
-
# ongoing profile is not lost if the process shuts down before the
|
70
|
-
# max request count is reached
|
71
|
-
ObjectSpace.define_finalizer(self, proc { print! })
|
72
|
-
end
|
49
|
+
@only_paths ? paths_match?(path, @only_paths) : true
|
50
|
+
end
|
73
51
|
|
74
|
-
|
75
|
-
|
76
|
-
|
52
|
+
def paths_match?(path, paths)
|
53
|
+
paths.any? { |skip_path| skip_path =~ path }
|
54
|
+
end
|
77
55
|
|
78
|
-
|
79
|
-
|
80
|
-
|
56
|
+
def profiling_options
|
57
|
+
options = {}
|
58
|
+
options[:measure_mode] = ::RubyProf.measure_mode
|
59
|
+
options[:exclude_threads] =
|
60
|
+
if @options[:ignore_existing_threads]
|
61
|
+
Thread.list.select{|t| t != Thread.current}
|
62
|
+
else
|
63
|
+
::RubyProf.exclude_threads
|
64
|
+
end
|
65
|
+
if @options[:request_thread_only]
|
66
|
+
options[:include_threads] = [Thread.current]
|
81
67
|
end
|
82
|
-
|
83
|
-
|
84
|
-
@requests_count >= @max_requests
|
68
|
+
if @options[:merge_fibers]
|
69
|
+
options[:merge_fibers] = true
|
85
70
|
end
|
71
|
+
options
|
72
|
+
end
|
86
73
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
data = @profile.stop
|
91
|
-
|
92
|
-
prefix ||= "multi-requests-#{@requests_count}"
|
93
|
-
|
94
|
-
@printer_klasses.each do |printer_klass, base_name|
|
95
|
-
printer = printer_klass.new(data)
|
96
|
-
|
97
|
-
if base_name.respond_to?(:call)
|
98
|
-
base_name = base_name.call
|
99
|
-
end
|
74
|
+
def print(data, path)
|
75
|
+
@printer_klasses.each do |printer_klass, base_name|
|
76
|
+
printer = printer_klass.new(data)
|
100
77
|
|
101
|
-
|
102
|
-
|
103
|
-
printer.print(@options.merge(:profile => "#{prefix}-#{base_name}"))
|
104
|
-
else
|
105
|
-
file_name = ::File.join(@tmpdir, "#{prefix}-#{base_name}")
|
106
|
-
::File.open(file_name, 'wb') do |file|
|
107
|
-
printer.print(file, @options)
|
108
|
-
end
|
109
|
-
end
|
78
|
+
if base_name.respond_to?(:call)
|
79
|
+
base_name = base_name.call
|
110
80
|
end
|
111
81
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
options[:exclude_threads] =
|
121
|
-
if @options[:ignore_existing_threads]
|
122
|
-
Thread.list.select{|t| t != Thread.current}
|
123
|
-
else
|
124
|
-
::RubyProf.exclude_threads
|
82
|
+
if printer_klass == ::RubyProf::MultiPrinter
|
83
|
+
printer.print(@options.merge(:profile => "#{path}-#{base_name}"))
|
84
|
+
elsif printer_klass == ::RubyProf::CallTreePrinter
|
85
|
+
printer.print(@options.merge(:profile => "#{path}-#{base_name}"))
|
86
|
+
else
|
87
|
+
file_name = ::File.join(@tmpdir, "#{path}-#{base_name}")
|
88
|
+
::File.open(file_name, 'wb') do |file|
|
89
|
+
printer.print(file, @options)
|
125
90
|
end
|
126
|
-
if @options[:request_thread_only]
|
127
|
-
options[:include_threads] = [Thread.current]
|
128
91
|
end
|
129
|
-
if @options[:merge_fibers]
|
130
|
-
options[:merge_fibers] = true
|
131
|
-
end
|
132
|
-
options
|
133
|
-
end
|
134
|
-
|
135
|
-
def default_printers
|
136
|
-
{::RubyProf::FlatPrinter => 'flat.txt',
|
137
|
-
::RubyProf::GraphPrinter => 'graph.txt',
|
138
|
-
::RubyProf::GraphHtmlPrinter => 'graph.html',
|
139
|
-
::RubyProf::CallStackPrinter => 'call_stack.html'}
|
140
92
|
end
|
141
93
|
end
|
142
|
-
|
143
|
-
def profiler
|
144
|
-
if aggregate_requests?
|
145
|
-
@@_shared_profiler ||= RackProfiler.new(@options)
|
146
|
-
else
|
147
|
-
@_profiler ||= RackProfiler.new(@options)
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
def delete_profiler!
|
152
|
-
if aggregate_requests?
|
153
|
-
@@_shared_profiler.print! if @@_shared_profiler
|
154
|
-
@@_shared_profiler = nil
|
155
|
-
else
|
156
|
-
@_profiler = nil
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
def aggregate_requests?
|
161
|
-
!@max_requests.nil?
|
162
|
-
end
|
163
|
-
|
164
|
-
def should_profile?(path)
|
165
|
-
return false if paths_match?(path, @skip_paths)
|
166
|
-
|
167
|
-
@only_paths ? paths_match?(path, @only_paths) : true
|
168
|
-
end
|
169
|
-
|
170
|
-
def paths_match?(path, paths)
|
171
|
-
paths.any? { |skip_path| skip_path =~ path }
|
172
|
-
end
|
173
94
|
end
|
174
95
|
end
|
data/lib/ruby-prof/version.rb
CHANGED
data/test/rack_test.rb
CHANGED
@@ -24,16 +24,6 @@ module Rack
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
module Rack
|
28
|
-
class RubyProf
|
29
|
-
attr_reader :_profiler
|
30
|
-
|
31
|
-
def public_delete_profiler!
|
32
|
-
delete_profiler!
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
27
|
class RackTest < TestCase
|
38
28
|
def test_create_print_path
|
39
29
|
path = Dir.mktmpdir
|
@@ -100,58 +90,4 @@ class RackTest < TestCase
|
|
100
90
|
file_path = ::File.join(path, 'path-to-resource.json-dynamic.txt')
|
101
91
|
assert(File.exist?(file_path))
|
102
92
|
end
|
103
|
-
|
104
|
-
def test_works_for_multiple_requests
|
105
|
-
path = Dir.mktmpdir
|
106
|
-
|
107
|
-
adapter = Rack::RubyProf.new(FakeRackApp.new, :path => path, :max_requests => 2)
|
108
|
-
|
109
|
-
# make a 1st request, and check that this didn't create any files
|
110
|
-
adapter.call(:fake_env)
|
111
|
-
assert(Dir["#{path}/*"].empty?)
|
112
|
-
|
113
|
-
# now a second request should create all the expected files
|
114
|
-
adapter.call(:fake_env)
|
115
|
-
%w(flat.txt graph.txt graph.html call_stack.html).each do |base_name|
|
116
|
-
file_path = ::File.join(path, "multi-requests-2-#{base_name}")
|
117
|
-
assert(File.exist?(file_path))
|
118
|
-
end
|
119
|
-
|
120
|
-
# let's clean up
|
121
|
-
FileUtils.rm_rf(Dir["#{path}/*"])
|
122
|
-
|
123
|
-
# and do the same again for the next 2 requests
|
124
|
-
adapter.call(:fake_env)
|
125
|
-
assert(Dir["#{path}/*"].empty?)
|
126
|
-
|
127
|
-
adapter.call(:fake_env)
|
128
|
-
%w(flat.txt graph.txt graph.html call_stack.html).each do |base_name|
|
129
|
-
file_path = ::File.join(path, "multi-requests-2-#{base_name}")
|
130
|
-
assert(File.exist?(file_path))
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
def test_tries_to_print_results_if_shut_down_before_max_requests_reached
|
135
|
-
path = Dir.mktmpdir
|
136
|
-
|
137
|
-
adapter = Rack::RubyProf.new(FakeRackApp.new, :path => path, :max_requests => 100)
|
138
|
-
|
139
|
-
# make a 1st request, and check that this didn't create any files
|
140
|
-
adapter.call(:fake_env)
|
141
|
-
assert(Dir["#{path}/*"].empty?)
|
142
|
-
|
143
|
-
adapter.public_delete_profiler!
|
144
|
-
|
145
|
-
%w(flat.txt graph.txt graph.html call_stack.html).each do |base_name|
|
146
|
-
file_path = ::File.join(path, "multi-requests-1-#{base_name}")
|
147
|
-
assert(File.exist?(file_path))
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
def test_it_uses_separate_profilers_if_not_aggregating_multiple_requests
|
152
|
-
adapter1 = Rack::RubyProf.new(FakeRackApp.new)
|
153
|
-
adapter2 = Rack::RubyProf.new(FakeRackApp.new)
|
154
|
-
|
155
|
-
assert(adapter1.object_id != adapter2.object_id)
|
156
|
-
end
|
157
93
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-prof
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shugo Maeda, Charlie Savage, Roger Pack, Stefan Kaes
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-04-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -177,7 +177,7 @@ metadata:
|
|
177
177
|
bug_tracker_uri: https://github.com/ruby-prof/ruby-prof/issues
|
178
178
|
changelog_uri: https://github.com/ruby-prof/ruby-prof/blob/master/CHANGES
|
179
179
|
documentation_uri: https://ruby-prof.github.io/
|
180
|
-
source_code_uri: https://github.com/ruby-prof/ruby-prof/tree/v1.3.
|
180
|
+
source_code_uri: https://github.com/ruby-prof/ruby-prof/tree/v1.3.2
|
181
181
|
post_install_message:
|
182
182
|
rdoc_options: []
|
183
183
|
require_paths:
|
@@ -193,7 +193,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
193
193
|
- !ruby/object:Gem::Version
|
194
194
|
version: '0'
|
195
195
|
requirements: []
|
196
|
-
rubygems_version: 3.
|
196
|
+
rubygems_version: 3.1.2
|
197
197
|
signing_key:
|
198
198
|
specification_version: 4
|
199
199
|
summary: Fast Ruby profiler
|