stackprof 0.2.19 → 0.2.20

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: 6662250e5e20ee3388bfce740a053c83e53fe9304b518ad22f0ce9ffc5d10077
4
- data.tar.gz: 7480e1896e253bd530573fc2f66b3d7690db97bee3f892c77729b75c2dc8c94e
3
+ metadata.gz: e627bf7fbeca0cb94e8be863b0a1db9160534d5172c1409ba4306e0f16a57ae0
4
+ data.tar.gz: f881ec5ab3267f3b48f57794c3bce910b39f890db32817655b4e5253733fc466
5
5
  SHA512:
6
- metadata.gz: 3f92e6401b16f83d9398b94e8b0506f597a785a19e1552245f39e1c77ab0c2d3d40186b8b05f91972b6d899995718c28e1724acff97248d497a3768deed601bb
7
- data.tar.gz: 0663a1cdac8730bcbc4dd68750fffa6885b72eca7c37915191b6ff44ff101349ba274648b6641531c1bfff34144179b76d527ca8426db91af2c0536629f6ee65
6
+ metadata.gz: 514c6697e4465fbce7990fffc2a71ca5aa544e1f526b338fde343c14bc801bb5056534e371e4d8fd5642f1b73b92126b2a5e476eb5292dde23bd0da734d7e236
7
+ data.tar.gz: bed130e196f1004b3e74d2db466732fa8b23e582df3fcf944161112036053e95a5a05a3ed2ac175a6603e1f3b28b6062491aef89f4d30b764be3886aaf586b19
@@ -8,7 +8,7 @@ jobs:
8
8
  strategy:
9
9
  fail-fast: false
10
10
  matrix:
11
- ruby: [ ruby-head, '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' ]
12
12
  steps:
13
13
  - name: Checkout
14
14
  uses: actions/checkout@v2
data/bin/stackprof CHANGED
@@ -42,7 +42,7 @@ reports = []
42
42
  while ARGV.size > 0
43
43
  begin
44
44
  file = ARGV.pop
45
- reports << StackProf::Report.new(Marshal.load(IO.binread(file)))
45
+ reports << StackProf::Report.from_file(file)
46
46
  rescue TypeError => e
47
47
  STDERR.puts "** error parsing #{file}: #{e.inspect}"
48
48
  end
@@ -25,20 +25,14 @@
25
25
  #define FAKE_FRAME_MARK INT2FIX(1)
26
26
  #define FAKE_FRAME_SWEEP INT2FIX(2)
27
27
 
28
- /*
29
- * As of Ruby 3.0, it should be safe to read stack frames at any time
30
- * See https://github.com/ruby/ruby/commit/0e276dc458f94d9d79a0f7c7669bde84abe80f21
31
- */
32
- #if RUBY_API_VERSION_MAJOR < 3
33
- #define USE_POSTPONED_JOB
34
- #endif
35
-
36
28
  static const char *fake_frame_cstrs[] = {
37
29
  "(garbage collection)",
38
30
  "(marking)",
39
31
  "(sweeping)",
40
32
  };
41
33
 
34
+ static int stackprof_use_postponed_job = 1;
35
+
42
36
  #define TOTAL_FAKE_FRAMES (sizeof(fake_frame_cstrs) / sizeof(char *))
43
37
 
44
38
  #ifdef _POSIX_MONOTONIC_CLOCK
@@ -701,7 +695,6 @@ stackprof_job_record_gc(void *data)
701
695
  stackprof_record_gc_samples();
702
696
  }
703
697
 
704
- #ifdef USE_POSTPONED_JOB
705
698
  static void
706
699
  stackprof_job_sample_and_record(void *data)
707
700
  {
@@ -709,7 +702,6 @@ stackprof_job_sample_and_record(void *data)
709
702
 
710
703
  stackprof_sample_and_record();
711
704
  }
712
- #endif
713
705
 
714
706
  static void
715
707
  stackprof_job_record_buffer(void *data)
@@ -740,15 +732,15 @@ stackprof_signal_handler(int sig, siginfo_t *sinfo, void *ucontext)
740
732
  _stackprof.unrecorded_gc_samples++;
741
733
  rb_postponed_job_register_one(0, stackprof_job_record_gc, (void*)0);
742
734
  } else {
743
- #ifdef USE_POSTPONED_JOB
744
- rb_postponed_job_register_one(0, stackprof_job_sample_and_record, (void*)0);
745
- #else
746
- // Buffer a sample immediately, if an existing sample exists this will
747
- // return immediately
748
- stackprof_buffer_sample();
749
- // Enqueue a job to record the sample
750
- rb_postponed_job_register_one(0, stackprof_job_record_buffer, (void*)0);
751
- #endif
735
+ if (stackprof_use_postponed_job) {
736
+ rb_postponed_job_register_one(0, stackprof_job_sample_and_record, (void*)0);
737
+ } else {
738
+ // Buffer a sample immediately, if an existing sample exists this will
739
+ // return immediately
740
+ stackprof_buffer_sample();
741
+ // Enqueue a job to record the sample
742
+ rb_postponed_job_register_one(0, stackprof_job_record_buffer, (void*)0);
743
+ }
752
744
  }
753
745
  pthread_mutex_unlock(&lock);
754
746
  }
@@ -826,9 +818,24 @@ stackprof_atfork_child(void)
826
818
  stackprof_stop(rb_mStackProf);
827
819
  }
828
820
 
821
+ static VALUE
822
+ stackprof_use_postponed_job_l(VALUE self)
823
+ {
824
+ stackprof_use_postponed_job = 1;
825
+ return Qnil;
826
+ }
827
+
829
828
  void
830
829
  Init_stackprof(void)
831
830
  {
831
+ /*
832
+ * As of Ruby 3.0, it should be safe to read stack frames at any time, unless YJIT is enabled
833
+ * See https://github.com/ruby/ruby/commit/0e276dc458f94d9d79a0f7c7669bde84abe80f21
834
+ */
835
+ #if RUBY_API_VERSION_MAJOR < 3
836
+ stackprof_use_postponed_job = 0;
837
+ #endif
838
+
832
839
  size_t i;
833
840
  #define S(name) sym_##name = ID2SYM(rb_intern(#name));
834
841
  S(object);
@@ -890,6 +897,7 @@ Init_stackprof(void)
890
897
  rb_define_singleton_method(rb_mStackProf, "stop", stackprof_stop, 0);
891
898
  rb_define_singleton_method(rb_mStackProf, "results", stackprof_results, -1);
892
899
  rb_define_singleton_method(rb_mStackProf, "sample", stackprof_sample, 0);
900
+ rb_define_singleton_method(rb_mStackProf, "use_postponed_job!", stackprof_use_postponed_job_l, 0);
893
901
 
894
902
  pthread_atfork(stackprof_atfork_prepare, stackprof_atfork_parent, stackprof_atfork_child);
895
903
  }
@@ -2,9 +2,43 @@
2
2
 
3
3
  require 'pp'
4
4
  require 'digest/md5'
5
+ require 'json'
5
6
 
6
7
  module StackProf
7
8
  class Report
9
+ MARSHAL_SIGNATURE = "\x04\x08"
10
+
11
+ class << self
12
+ def from_file(file)
13
+ if (content = IO.binread(file)).start_with?(MARSHAL_SIGNATURE)
14
+ new(Marshal.load(content))
15
+ else
16
+ from_json(JSON.parse(content))
17
+ end
18
+ end
19
+
20
+ def from_json(json)
21
+ new(parse_json(json))
22
+ end
23
+
24
+ def parse_json(json)
25
+ json.keys.each do |key|
26
+ value = json.delete(key)
27
+ from_json(value) if value.is_a?(Hash)
28
+
29
+ new_key = case key
30
+ when /\A[0-9]*\z/
31
+ key.to_i
32
+ else
33
+ key.to_sym
34
+ end
35
+
36
+ json[new_key] = value
37
+ end
38
+ json
39
+ end
40
+ end
41
+
8
42
  def initialize(data)
9
43
  @data = data
10
44
  end
data/lib/stackprof.rb CHANGED
@@ -1,7 +1,11 @@
1
1
  require "stackprof/stackprof"
2
2
 
3
+ if defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?
4
+ StackProf.use_postponed_job!
5
+ end
6
+
3
7
  module StackProf
4
- VERSION = '0.2.19'
8
+ VERSION = '0.2.20'
5
9
  end
6
10
 
7
11
  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.19'
3
+ s.version = '0.2.20'
4
4
  s.homepage = 'http://github.com/tmm1/stackprof'
5
5
 
6
6
  s.authors = 'Aman Gupta'
@@ -0,0 +1 @@
1
+ {: modeI"cpu:ET
@@ -0,0 +1 @@
1
+ { "mode": "cpu" }
data/test/test_report.rb CHANGED
@@ -32,3 +32,27 @@ class ReportDumpTest < MiniTest::Test
32
32
  assert_equal expected, Marshal.load(marshal_data)
33
33
  end
34
34
  end
35
+
36
+ class ReportReadTest < MiniTest::Test
37
+ require 'pathname'
38
+
39
+ def test_from_file_read_json
40
+ file = fixture("profile.json")
41
+ report = StackProf::Report.from_file(file)
42
+
43
+ assert_equal({ mode: "cpu" }, report.data)
44
+ end
45
+
46
+ def test_from_file_read_marshal
47
+ file = fixture("profile.dump")
48
+ report = StackProf::Report.from_file(file)
49
+
50
+ assert_equal({ mode: "cpu" }, report.data)
51
+ end
52
+
53
+ private
54
+
55
+ def fixture(name)
56
+ Pathname.new(__dir__).join("fixtures", name)
57
+ end
58
+ end
@@ -5,6 +5,10 @@ require 'tempfile'
5
5
  require 'pathname'
6
6
 
7
7
  class StackProfTest < MiniTest::Test
8
+ def setup
9
+ Object.new # warm some caches to avoid flakiness
10
+ end
11
+
8
12
  def test_info
9
13
  profile = StackProf.run{}
10
14
  assert_equal 1.2, profile[:version]
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.19
4
+ version: 0.2.20
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-02-24 00:00:00.000000000 Z
11
+ date: 2022-07-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -82,6 +82,8 @@ files:
82
82
  - lib/stackprof/report.rb
83
83
  - sample.rb
84
84
  - stackprof.gemspec
85
+ - test/fixtures/profile.dump
86
+ - test/fixtures/profile.json
85
87
  - test/test_middleware.rb
86
88
  - test/test_report.rb
87
89
  - test/test_stackprof.rb
@@ -94,9 +96,9 @@ licenses:
94
96
  - MIT
95
97
  metadata:
96
98
  bug_tracker_uri: https://github.com/tmm1/stackprof/issues
97
- changelog_uri: https://github.com/tmm1/stackprof/blob/v0.2.19/CHANGELOG.md
98
- documentation_uri: https://www.rubydoc.info/gems/stackprof/0.2.19
99
- source_code_uri: https://github.com/tmm1/stackprof/tree/v0.2.19
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
100
102
  post_install_message:
101
103
  rdoc_options: []
102
104
  require_paths: