stackprof 0.2.19 → 0.2.20

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: 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: