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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: de991aaaa9b3bae6b7d38da2adac6112e7f254d2927ec3e6cb6e7d1d07fb4c7b
4
- data.tar.gz: 1f246cf6795b6cb955188349c5f4da06e95a3fd94241fbd29aab8dcdcd19d312
3
+ metadata.gz: 9dbafd0a6aebb3d09c5f7f198d4261fbd39709c33ec216ea542e8fe2063cd2b9
4
+ data.tar.gz: f66379b3e8b2c5fde1ef01ce84484a6b9f958bb643c4783e32fd6b37f033efb0
5
5
  SHA512:
6
- metadata.gz: bc39dad6f9d5795ba4f48fa674097798de0be279ea9ccae63c2a7c683f22031bbf6bda85b81b46bccd8b4112d30e65b40d5a5dac9311ced4d033f3ccb32fd2de
7
- data.tar.gz: bf04b46a607a9ff896fc6d8eb169447920136ce5a713132993d2f1e830b215c4fa97f9c43253024ddebb289bc5b3f1ceba0200579796f28a9e31c6faffedb698
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 = ['x86-mingw32', 'x64-mingw32']
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
@@ -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
- RUBY_VERSION =~ /(\d+\.\d+\.\d+)/
6
- require "#{$1}/ruby_prof.so"
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
@@ -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[:min_percent] ||= 1
11
+ @tmpdir = options[:path] || Dir.tmpdir
12
+ FileUtils.mkdir_p(@tmpdir)
10
13
 
11
- options[:path] ||= Dir.tmpdir
12
- FileUtils.mkdir_p(options[:path])
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 = @app.call(env)
29
- ensure
30
- profiler.pause
31
- end
28
+ result = nil
29
+ data = ::RubyProf::Profile.profile(profiling_options) do
30
+ result = @app.call(env)
31
+ end
32
32
 
33
- if profiler.max_requests_reached?
34
- prefix = if aggregate_requests?
35
- nil
36
- else
37
- request.path.gsub('/', '-')[1..-1]
38
- end
33
+ path = request.path.gsub('/', '-')
34
+ path.slice!(0)
39
35
 
40
- profiler.print!(prefix)
41
- delete_profiler!
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
- class RackProfiler
53
- def initialize(options)
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
- @printed = false
68
- # if running across multiple requests, we want to make sure that the
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
- def resume
75
- @profile.resume
76
- end
52
+ def paths_match?(path, paths)
53
+ paths.any? { |skip_path| skip_path =~ path }
54
+ end
77
55
 
78
- def pause
79
- @profile.pause
80
- @requests_count += 1
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
- def max_requests_reached?
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
- def print!(prefix = nil)
88
- return false if @printed || @requests_count == 0
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
- if printer_klass == ::RubyProf::MultiPrinter \
102
- || printer_klass == ::RubyProf::CallTreePrinter
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
- @printed = true
113
- end
114
-
115
- private
116
-
117
- def profiling_options
118
- options = {}
119
- options[:measure_mode] = ::RubyProf.measure_mode
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
@@ -1,3 +1,3 @@
1
1
  module RubyProf
2
- VERSION = "1.3.1"
2
+ VERSION = "1.3.2"
3
3
  end
@@ -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.1
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-03-12 00:00:00.000000000 Z
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.1
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.0.6
196
+ rubygems_version: 3.1.2
197
197
  signing_key:
198
198
  specification_version: 4
199
199
  summary: Fast Ruby profiler