stackprof 0.2.20 → 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: e627bf7fbeca0cb94e8be863b0a1db9160534d5172c1409ba4306e0f16a57ae0
4
- data.tar.gz: f881ec5ab3267f3b48f57794c3bce910b39f890db32817655b4e5253733fc466
3
+ metadata.gz: 8e473c6b4408f04dc69f4abd425ab68896b4f705adadd467ded771003eb84da1
4
+ data.tar.gz: 5bfaa3c22d7e59271f65136b0237cddc4d1a97edf9650db4caf53c9b36fda55e
5
5
  SHA512:
6
- metadata.gz: 514c6697e4465fbce7990fffc2a71ca5aa544e1f526b338fde343c14bc801bb5056534e371e4d8fd5642f1b73b92126b2a5e476eb5292dde23bd0da734d7e236
7
- data.tar.gz: bed130e196f1004b3e74d2db466732fa8b23e582df3fcf944161112036053e95a5a05a3ed2ac175a6603e1f3b28b6062491aef89f4d30b764be3886aaf586b19
6
+ metadata.gz: eb0ffc8bac6c1c66b13ce67d89bac3fbd1c601754024c3e8455e194a35e58f3c515586aa0ffeee4e30985a6e140ce64724c0960dce8de67d8a3e0f0e912d3898
7
+ data.tar.gz: 4cfc9aa211ab10a7b0a0c222e94538311bd91950fa32fc0602e2535468df4c48158219cad2f2f6fee015f94a9b415c3a285406fcc66ab27676a6572492b2d7f9
@@ -8,7 +8,7 @@ jobs:
8
8
  strategy:
9
9
  fail-fast: false
10
10
  matrix:
11
- ruby: [ ruby-head, '3.1', '3.0', '2.7', '2.6', '2.5', '2.4', '2.3', '2.2' ]
11
+ ruby: [ ruby-head, '3.1', '3.0', '2.7', '2.6', '2.5', '2.4', '2.3', '2.2', truffleruby ]
12
12
  steps:
13
13
  - name: Checkout
14
14
  uses: actions/checkout@v2
data/Rakefile CHANGED
@@ -7,11 +7,21 @@ Rake::TestTask.new(:test) do |t|
7
7
  t.test_files = FileList["test/**/test_*.rb"]
8
8
  end
9
9
 
10
- require "rake/extensiontask"
10
+ if RUBY_ENGINE == "truffleruby"
11
+ task :compile do
12
+ # noop
13
+ end
11
14
 
12
- Rake::ExtensionTask.new("stackprof") do |ext|
13
- ext.ext_dir = "ext/stackprof"
14
- ext.lib_dir = "lib/stackprof"
15
+ task :clean do
16
+ # noop
17
+ end
18
+ else
19
+ require "rake/extensiontask"
20
+
21
+ Rake::ExtensionTask.new("stackprof") do |ext|
22
+ ext.ext_dir = "ext/stackprof"
23
+ ext.lib_dir = "lib/stackprof"
24
+ end
15
25
  end
16
26
 
17
27
  task default: %i(compile test)
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
@@ -1,4 +1,10 @@
1
1
  require 'mkmf'
2
+
3
+ if RUBY_ENGINE == 'truffleruby'
4
+ File.write('Makefile', dummy_makefile($srcdir).join(""))
5
+ return
6
+ end
7
+
2
8
  if have_func('rb_postponed_job_register_one') &&
3
9
  have_func('rb_profile_frames') &&
4
10
  have_func('rb_tracepoint_new') &&
@@ -146,6 +146,7 @@ stackprof_start(int argc, VALUE *argv, VALUE self)
146
146
  VALUE opts = Qnil, mode = Qnil, interval = Qnil, metadata = rb_hash_new(), out = Qfalse;
147
147
  int ignore_gc = 0;
148
148
  int raw = 0, aggregate = 1;
149
+ VALUE metadata_val;
149
150
 
150
151
  if (_stackprof.running)
151
152
  return Qfalse;
@@ -160,7 +161,7 @@ stackprof_start(int argc, VALUE *argv, VALUE self)
160
161
  ignore_gc = 1;
161
162
  }
162
163
 
163
- VALUE metadata_val = rb_hash_aref(opts, sym_metadata);
164
+ metadata_val = rb_hash_aref(opts, sym_metadata);
164
165
  if (RTEST(metadata_val)) {
165
166
  if (!RB_TYPE_P(metadata_val, T_HASH))
166
167
  rb_raise(rb_eArgError, "metadata should be a hash");
@@ -597,14 +598,15 @@ stackprof_record_sample_for_stack(int num, uint64_t sample_timestamp, int64_t ti
597
598
  void
598
599
  stackprof_buffer_sample(void)
599
600
  {
601
+ uint64_t start_timestamp = 0;
602
+ int64_t timestamp_delta = 0;
603
+ int num;
604
+
600
605
  if (_stackprof.buffer_count > 0) {
601
606
  // Another sample is already pending
602
607
  return;
603
608
  }
604
609
 
605
- uint64_t start_timestamp = 0;
606
- int64_t timestamp_delta = 0;
607
- int num;
608
610
  if (_stackprof.raw) {
609
611
  struct timestamp_t t;
610
612
  capture_timestamp(&t);
@@ -828,15 +830,13 @@ stackprof_use_postponed_job_l(VALUE self)
828
830
  void
829
831
  Init_stackprof(void)
830
832
  {
833
+ size_t i;
831
834
  /*
832
835
  * As of Ruby 3.0, it should be safe to read stack frames at any time, unless YJIT is enabled
833
836
  * See https://github.com/ruby/ruby/commit/0e276dc458f94d9d79a0f7c7669bde84abe80f21
834
837
  */
835
- #if RUBY_API_VERSION_MAJOR < 3
836
- stackprof_use_postponed_job = 0;
837
- #endif
838
+ stackprof_use_postponed_job = RUBY_API_VERSION_MAJOR < 3;
838
839
 
839
- size_t i;
840
840
  #define S(name) sym_##name = ID2SYM(rb_intern(#name));
841
841
  S(object);
842
842
  S(custom);
@@ -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)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'pp'
4
- require 'digest/md5'
4
+ require 'digest/sha2'
5
5
  require 'json'
6
6
 
7
7
  module StackProf
@@ -52,7 +52,7 @@ module StackProf
52
52
  def normalized_frames
53
53
  id2hash = {}
54
54
  @data[:frames].each do |frame, info|
55
- id2hash[frame.to_s] = info[:hash] = Digest::MD5.hexdigest("#{info[:name]}#{info[:file]}#{info[:line]}")
55
+ id2hash[frame.to_s] = info[:hash] = Digest::SHA256.hexdigest("#{info[:name]}#{info[:file]}#{info[:line]}")
56
56
  end
57
57
  @data[:frames].inject(Hash.new) do |hash, (frame, info)|
58
58
  info = hash[id2hash[frame.to_s]] = info.dup
@@ -225,7 +225,7 @@ module StackProf
225
225
  end
226
226
  else
227
227
  frame = @data[:frames][val]
228
- child_name = "#{ frame[:name] } : #{ frame[:file] }"
228
+ child_name = "#{ frame[:name] } : #{ frame[:file] } : #{ frame[:line] }"
229
229
  child_data = convert_to_d3_flame_graph_format(child_name, child_stacks, depth + 1)
230
230
  weight += child_data["value"]
231
231
  children << child_data
@@ -0,0 +1,37 @@
1
+ module StackProf
2
+ # Define the same methods as stackprof.c
3
+ class << self
4
+ def running?
5
+ false
6
+ end
7
+
8
+ def run(*args)
9
+ unimplemented
10
+ end
11
+
12
+ def start(*args)
13
+ unimplemented
14
+ end
15
+
16
+ def stop
17
+ unimplemented
18
+ end
19
+
20
+ def results(*args)
21
+ unimplemented
22
+ end
23
+
24
+ def sample
25
+ unimplemented
26
+ end
27
+
28
+ def use_postponed_job!
29
+ # noop
30
+ end
31
+
32
+ private def unimplemented
33
+ raise "Use --cpusampler=flamegraph or --cpusampler instead of StackProf on TruffleRuby.\n" \
34
+ "See https://www.graalvm.org/tools/profiling/ and `ruby --help:cpusampler` for more details."
35
+ end
36
+ end
37
+ end
data/lib/stackprof.rb CHANGED
@@ -1,11 +1,15 @@
1
- require "stackprof/stackprof"
1
+ if RUBY_ENGINE == 'truffleruby'
2
+ require "stackprof/truffleruby"
3
+ else
4
+ require "stackprof/stackprof"
5
+ end
2
6
 
3
7
  if defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?
4
8
  StackProf.use_postponed_job!
5
9
  end
6
10
 
7
11
  module StackProf
8
- VERSION = '0.2.20'
12
+ VERSION = '0.2.22'
9
13
  end
10
14
 
11
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.20'
3
+ s.version = '0.2.22'
4
4
  s.homepage = 'http://github.com/tmm1/stackprof'
5
5
 
6
6
  s.authors = 'Aman Gupta'
@@ -308,4 +308,4 @@ class StackProfTest < MiniTest::Test
308
308
  r.close
309
309
  w.close
310
310
  end
311
- end
311
+ end unless RUBY_ENGINE == 'truffleruby'
@@ -0,0 +1,18 @@
1
+ $:.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'stackprof'
3
+ require 'minitest/autorun'
4
+
5
+ if RUBY_ENGINE == 'truffleruby'
6
+ class StackProfTruffleRubyTest < MiniTest::Test
7
+ def test_error
8
+ error = assert_raises RuntimeError do
9
+ StackProf.run(mode: :cpu) do
10
+ unreacheable
11
+ end
12
+ end
13
+
14
+ assert_match(/TruffleRuby/, error.message)
15
+ assert_match(/--cpusampler/, error.message)
16
+ end
17
+ end
18
+ end
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.20
4
+ version: 0.2.22
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aman Gupta
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-07-26 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,10 +76,12 @@ 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
82
83
  - lib/stackprof/report.rb
84
+ - lib/stackprof/truffleruby.rb
83
85
  - sample.rb
84
86
  - stackprof.gemspec
85
87
  - test/fixtures/profile.dump
@@ -87,6 +89,7 @@ files:
87
89
  - test/test_middleware.rb
88
90
  - test/test_report.rb
89
91
  - test/test_stackprof.rb
92
+ - test/test_truffleruby.rb
90
93
  - vendor/FlameGraph/README
91
94
  - vendor/FlameGraph/flamegraph.pl
92
95
  - vendor/gprof2dot/gprof2dot.py
@@ -96,9 +99,9 @@ licenses:
96
99
  - MIT
97
100
  metadata:
98
101
  bug_tracker_uri: https://github.com/tmm1/stackprof/issues
99
- changelog_uri: https://github.com/tmm1/stackprof/blob/v0.2.20/CHANGELOG.md
100
- documentation_uri: https://www.rubydoc.info/gems/stackprof/0.2.20
101
- source_code_uri: https://github.com/tmm1/stackprof/tree/v0.2.20
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
102
105
  post_install_message:
103
106
  rdoc_options: []
104
107
  require_paths: