stackprof 0.2.21 → 0.2.22

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33a342cae97be870781375a647e95936c6a6016ae711f27d60e41a891cb809f4
4
- data.tar.gz: 867d55b7c7cdfc928ae35b3c36474bdda41ed4c4dc8e8b661b0c6580890b0b28
3
+ metadata.gz: 8e473c6b4408f04dc69f4abd425ab68896b4f705adadd467ded771003eb84da1
4
+ data.tar.gz: 5bfaa3c22d7e59271f65136b0237cddc4d1a97edf9650db4caf53c9b36fda55e
5
5
  SHA512:
6
- metadata.gz: 255835983ab93b52f7d1118a076f1881511c27b82a6db9e3f5db909f888bb563b26b855fc49dacbd0ef0b41f77af6c7638bf15721ff5085d012e916d4871592f
7
- data.tar.gz: 7520e06a5bdf8fb240538b9a333f265675cc4056bc24b88c06d0d8c2e7cd5185346be6268707fe00f7f41bf6f8c8d70abc3925e53ac6684889ef4dc9e3ef6afd
6
+ metadata.gz: eb0ffc8bac6c1c66b13ce67d89bac3fbd1c601754024c3e8455e194a35e58f3c515586aa0ffeee4e30985a6e140ce64724c0960dce8de67d8a3e0f0e912d3898
7
+ data.tar.gz: 4cfc9aa211ab10a7b0a0c222e94538311bd91950fa32fc0602e2535468df4c48158219cad2f2f6fee015f94a9b415c3a285406fcc66ab27676a6572492b2d7f9
data/bin/stackprof CHANGED
@@ -2,94 +2,129 @@
2
2
  require 'optparse'
3
3
  require 'stackprof'
4
4
 
5
- options = {}
5
+ if ARGV.first == "run"
6
+ ARGV.shift
7
+ env = {}
8
+ parser = OptionParser.new(ARGV) do |o|
9
+ o.banner = "Usage: stackprof run [--mode|--out|--interval] -- COMMAND"
10
+ o.banner = "Usage: stackprof [file.dump]+ [--text|--method=NAME|--callgrind|--graphviz]"
6
11
 
7
- parser = OptionParser.new(ARGV) do |o|
8
- o.banner = "Usage: stackprof [file.dump]+ [--text|--method=NAME|--callgrind|--graphviz]"
12
+ o.on('--mode', 'Mode of sampling: cpu, wall, object, default to wall') do |mode|
13
+ env["STACKPROF_MODE"] = mode
14
+ end
9
15
 
10
- o.on('--text', 'Text summary per method (default)'){ options[:format] = :text }
11
- o.on('--json', 'JSON output (use with web viewers)'){ options[:format] = :json }
12
- o.on('--files', 'List of files'){ |f| options[:format] = :files }
13
- o.on('--limit [num]', Integer, 'Limit --text, --files, or --graphviz output to N entries'){ |n| options[:limit] = n }
14
- o.on('--sort-total', "Sort --text or --files output on total samples\n\n"){ options[:sort] = true }
15
- o.on('--method [grep]', 'Zoom into specified method'){ |f| options[:format] = :method; options[:filter] = f }
16
- o.on('--file [grep]', "Show annotated code for specified file"){ |f| options[:format] = :file; options[:filter] = f }
17
- o.on('--walk', "Walk the stacktrace interactively\n\n"){ |f| options[:walk] = true }
18
- o.on('--callgrind', 'Callgrind output (use with kcachegrind, stackprof-gprof2dot.py)'){ options[:format] = :callgrind }
19
- o.on('--graphviz', "Graphviz output (use with dot)"){ options[:format] = :graphviz }
20
- o.on('--node-fraction [frac]', OptionParser::DecimalNumeric, 'Drop nodes representing less than [frac] fraction of samples'){ |n| options[:node_fraction] = n }
21
- o.on('--stackcollapse', 'stackcollapse.pl compatible output (use with stackprof-flamegraph.pl)'){ options[:format] = :stackcollapse }
22
- o.on('--timeline-flamegraph', "timeline-flamegraph output (js)"){ options[:format] = :timeline_flamegraph }
23
- o.on('--alphabetical-flamegraph', "alphabetical-flamegraph output (js)"){ options[:format] = :alphabetical_flamegraph }
24
- o.on('--flamegraph', "alias to --timeline-flamegraph"){ options[:format] = :timeline_flamegraph }
25
- o.on('--flamegraph-viewer [f.js]', String, "open html viewer for flamegraph output"){ |file|
26
- puts("open file://#{File.expand_path('../../lib/stackprof/flamegraph/viewer.html', __FILE__)}?data=#{File.expand_path(file)}")
27
- exit
28
- }
29
- o.on('--d3-flamegraph', "flamegraph output (html using d3-flame-graph)\n\n"){ options[:format] = :d3_flamegraph }
30
- o.on('--select-files []', String, 'Show results of matching files'){ |path| (options[:select_files] ||= []) << File.expand_path(path) }
31
- o.on('--reject-files []', String, 'Exclude results of matching files'){ |path| (options[:reject_files] ||= []) << File.expand_path(path) }
32
- o.on('--select-names []', Regexp, 'Show results of matching method names'){ |regexp| (options[:select_names] ||= []) << regexp }
33
- o.on('--reject-names []', Regexp, 'Exclude results of matching method names'){ |regexp| (options[:reject_names] ||= []) << regexp }
34
- o.on('--dump', 'Print marshaled profile dump (combine multiple profiles)'){ options[:format] = :dump }
35
- o.on('--debug', 'Pretty print raw profile data'){ options[:format] = :debug }
36
- end
16
+ o.on('--out', 'The target file, which will be overwritten. Defaults to a random temporary file') do |out|
17
+ env['STACKPROF_OUT'] = out
18
+ end
37
19
 
38
- parser.parse!
39
- parser.abort(parser.help) if ARGV.empty?
20
+ o.on('--interval', 'Mode-relative sample rate') do |interval|
21
+ env['STACKPROF_INTERVAL'] = Integer(interval).to_s
22
+ end
40
23
 
41
- reports = []
42
- while ARGV.size > 0
43
- begin
44
- file = ARGV.pop
45
- reports << StackProf::Report.from_file(file)
46
- rescue TypeError => e
47
- STDERR.puts "** error parsing #{file}: #{e.inspect}"
24
+ o.on('--raw', 'collects the extra data required by the --flamegraph and --stackcollapse report types') do
25
+ env['STACKPROF_RAW'] = '1'
26
+ end
27
+
28
+ o.on('--ignore-gc', 'Ignore garbage collection frames') do
29
+ env['STACKPROF_IGNORE_GC'] = '1'
30
+ end
48
31
  end
49
- end
50
- report = reports.inject(:+)
32
+ parser.parse!
33
+ parser.abort(parser.help) if ARGV.empty?
34
+ stackprof_path = File.expand_path('../lib', __dir__)
35
+ env['RUBYOPT'] = "-I #{stackprof_path} -r stackprof/autorun #{ENV['RUBYOPT']}"
36
+ Kernel.exec(env, *ARGV)
37
+ else
38
+ options = {}
51
39
 
52
- default_options = {
53
- :format => :text,
54
- :sort => false,
55
- :limit => 30
56
- }
40
+ parser = OptionParser.new(ARGV) do |o|
41
+ o.banner = "Usage: stackprof run [--mode|--out|--interval] -- COMMAND"
42
+ o.banner = "Usage: stackprof [file.dump]+ [--text|--method=NAME|--callgrind|--graphviz]"
57
43
 
58
- if options[:format] == :graphviz
59
- default_options[:limit] = 120
60
- default_options[:node_fraction] = 0.005
61
- end
44
+ o.on('--text', 'Text summary per method (default)'){ options[:format] = :text }
45
+ o.on('--json', 'JSON output (use with web viewers)'){ options[:format] = :json }
46
+ o.on('--files', 'List of files'){ |f| options[:format] = :files }
47
+ o.on('--limit [num]', Integer, 'Limit --text, --files, or --graphviz output to N entries'){ |n| options[:limit] = n }
48
+ o.on('--sort-total', "Sort --text or --files output on total samples\n\n"){ options[:sort] = true }
49
+ o.on('--method [grep]', 'Zoom into specified method'){ |f| options[:format] = :method; options[:filter] = f }
50
+ o.on('--file [grep]', "Show annotated code for specified file"){ |f| options[:format] = :file; options[:filter] = f }
51
+ o.on('--walk', "Walk the stacktrace interactively\n\n"){ |f| options[:walk] = true }
52
+ o.on('--callgrind', 'Callgrind output (use with kcachegrind, stackprof-gprof2dot.py)'){ options[:format] = :callgrind }
53
+ o.on('--graphviz', "Graphviz output (use with dot)"){ options[:format] = :graphviz }
54
+ o.on('--node-fraction [frac]', OptionParser::DecimalNumeric, 'Drop nodes representing less than [frac] fraction of samples'){ |n| options[:node_fraction] = n }
55
+ o.on('--stackcollapse', 'stackcollapse.pl compatible output (use with stackprof-flamegraph.pl)'){ options[:format] = :stackcollapse }
56
+ o.on('--timeline-flamegraph', "timeline-flamegraph output (js)"){ options[:format] = :timeline_flamegraph }
57
+ o.on('--alphabetical-flamegraph', "alphabetical-flamegraph output (js)"){ options[:format] = :alphabetical_flamegraph }
58
+ o.on('--flamegraph', "alias to --timeline-flamegraph"){ options[:format] = :timeline_flamegraph }
59
+ o.on('--flamegraph-viewer [f.js]', String, "open html viewer for flamegraph output"){ |file|
60
+ puts("open file://#{File.expand_path('../../lib/stackprof/flamegraph/viewer.html', __FILE__)}?data=#{File.expand_path(file)}")
61
+ exit
62
+ }
63
+ o.on('--d3-flamegraph', "flamegraph output (html using d3-flame-graph)\n\n"){ options[:format] = :d3_flamegraph }
64
+ o.on('--select-files []', String, 'Show results of matching files'){ |path| (options[:select_files] ||= []) << File.expand_path(path) }
65
+ o.on('--reject-files []', String, 'Exclude results of matching files'){ |path| (options[:reject_files] ||= []) << File.expand_path(path) }
66
+ o.on('--select-names []', Regexp, 'Show results of matching method names'){ |regexp| (options[:select_names] ||= []) << regexp }
67
+ o.on('--reject-names []', Regexp, 'Exclude results of matching method names'){ |regexp| (options[:reject_names] ||= []) << regexp }
68
+ o.on('--dump', 'Print marshaled profile dump (combine multiple profiles)'){ options[:format] = :dump }
69
+ o.on('--debug', 'Pretty print raw profile data'){ options[:format] = :debug }
70
+ end
62
71
 
63
- options = default_options.merge(options)
64
- options.delete(:limit) if options[:limit] == 0
72
+ parser.parse!
73
+ parser.abort(parser.help) if ARGV.empty?
65
74
 
66
- case options[:format]
67
- when :text
68
- report.print_text(options[:sort], options[:limit], options[:select_files], options[:reject_files], options[:select_names], options[:reject_names])
69
- when :json
70
- report.print_json
71
- when :debug
72
- report.print_debug
73
- when :dump
74
- report.print_dump
75
- when :callgrind
76
- report.print_callgrind
77
- when :graphviz
78
- report.print_graphviz(options)
79
- when :stackcollapse
80
- report.print_stackcollapse
81
- when :timeline_flamegraph
82
- report.print_timeline_flamegraph
83
- when :alphabetical_flamegraph
84
- report.print_alphabetical_flamegraph
85
- when :d3_flamegraph
86
- report.print_d3_flamegraph
87
- when :method
88
- options[:walk] ? report.walk_method(options[:filter]) : report.print_method(options[:filter])
89
- when :file
90
- report.print_file(options[:filter])
91
- when :files
92
- report.print_files(options[:sort], options[:limit])
93
- else
94
- raise ArgumentError, "unknown format: #{options[:format]}"
75
+ reports = []
76
+ while ARGV.size > 0
77
+ begin
78
+ file = ARGV.pop
79
+ reports << StackProf::Report.from_file(file)
80
+ rescue TypeError => e
81
+ STDERR.puts "** error parsing #{file}: #{e.inspect}"
82
+ end
83
+ end
84
+ report = reports.inject(:+)
85
+
86
+ default_options = {
87
+ :format => :text,
88
+ :sort => false,
89
+ :limit => 30
90
+ }
91
+
92
+ if options[:format] == :graphviz
93
+ default_options[:limit] = 120
94
+ default_options[:node_fraction] = 0.005
95
+ end
96
+
97
+ options = default_options.merge(options)
98
+ options.delete(:limit) if options[:limit] == 0
99
+
100
+ case options[:format]
101
+ when :text
102
+ report.print_text(options[:sort], options[:limit], options[:select_files], options[:reject_files], options[:select_names], options[:reject_names])
103
+ when :json
104
+ report.print_json
105
+ when :debug
106
+ report.print_debug
107
+ when :dump
108
+ report.print_dump
109
+ when :callgrind
110
+ report.print_callgrind
111
+ when :graphviz
112
+ report.print_graphviz(options)
113
+ when :stackcollapse
114
+ report.print_stackcollapse
115
+ when :timeline_flamegraph
116
+ report.print_timeline_flamegraph
117
+ when :alphabetical_flamegraph
118
+ report.print_alphabetical_flamegraph
119
+ when :d3_flamegraph
120
+ report.print_d3_flamegraph
121
+ when :method
122
+ options[:walk] ? report.walk_method(options[:filter]) : report.print_method(options[:filter])
123
+ when :file
124
+ report.print_file(options[:filter])
125
+ when :files
126
+ report.print_files(options[:sort], options[:limit])
127
+ else
128
+ raise ArgumentError, "unknown format: #{options[:format]}"
129
+ end
95
130
  end
@@ -0,0 +1,19 @@
1
+ require "stackprof"
2
+
3
+ options = {}
4
+ options[:mode] = ENV["STACKPROF_MODE"].to_sym if ENV.key?("STACKPROF_MODE")
5
+ options[:interval] = Integer(ENV["STACKPROF_INTERVAL"]) if ENV.key?("STACKPROF_INTERVAL")
6
+ options[:raw] = true if ENV["STACKPROF_RAW"]
7
+ options[:ignore_gc] = true if ENV["STACKPROF_IGNORE_GC"]
8
+
9
+ at_exit do
10
+ StackProf.stop
11
+ output_path = ENV.fetch("STACKPROF_OUT") do
12
+ require "tempfile"
13
+ Tempfile.create(["stackprof", ".dump"]).path
14
+ end
15
+ StackProf.results(output_path)
16
+ $stderr.puts("StackProf results dumped at: #{output_path}")
17
+ end
18
+
19
+ StackProf.start(**options)
data/lib/stackprof.rb CHANGED
@@ -9,7 +9,7 @@ if defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?
9
9
  end
10
10
 
11
11
  module StackProf
12
- VERSION = '0.2.21'
12
+ VERSION = '0.2.22'
13
13
  end
14
14
 
15
15
  StackProf.autoload :Report, "stackprof/report.rb"
data/stackprof.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'stackprof'
3
- s.version = '0.2.21'
3
+ s.version = '0.2.22'
4
4
  s.homepage = 'http://github.com/tmm1/stackprof'
5
5
 
6
6
  s.authors = 'Aman Gupta'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stackprof
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.21
4
+ version: 0.2.22
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aman Gupta
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-22 00:00:00.000000000 Z
11
+ date: 2022-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -76,6 +76,7 @@ files:
76
76
  - ext/stackprof/extconf.rb
77
77
  - ext/stackprof/stackprof.c
78
78
  - lib/stackprof.rb
79
+ - lib/stackprof/autorun.rb
79
80
  - lib/stackprof/flamegraph/flamegraph.js
80
81
  - lib/stackprof/flamegraph/viewer.html
81
82
  - lib/stackprof/middleware.rb
@@ -98,10 +99,10 @@ licenses:
98
99
  - MIT
99
100
  metadata:
100
101
  bug_tracker_uri: https://github.com/tmm1/stackprof/issues
101
- changelog_uri: https://github.com/tmm1/stackprof/blob/v0.2.21/CHANGELOG.md
102
- documentation_uri: https://www.rubydoc.info/gems/stackprof/0.2.21
103
- source_code_uri: https://github.com/tmm1/stackprof/tree/v0.2.21
104
- post_install_message:
102
+ changelog_uri: https://github.com/tmm1/stackprof/blob/v0.2.22/CHANGELOG.md
103
+ documentation_uri: https://www.rubydoc.info/gems/stackprof/0.2.22
104
+ source_code_uri: https://github.com/tmm1/stackprof/tree/v0.2.22
105
+ post_install_message:
105
106
  rdoc_options: []
106
107
  require_paths:
107
108
  - lib
@@ -116,8 +117,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
117
  - !ruby/object:Gem::Version
117
118
  version: '0'
118
119
  requirements: []
119
- rubygems_version: 3.4.0.dev
120
- signing_key:
120
+ rubygems_version: 3.0.3.1
121
+ signing_key:
121
122
  specification_version: 4
122
123
  summary: sampling callstack-profiler for ruby 2.2+
123
124
  test_files: []