vernier 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/vernier.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative "vernier/version"
4
4
  require_relative "vernier/collector"
5
+ require_relative "vernier/result"
5
6
  require_relative "vernier/vernier"
6
7
  require_relative "vernier/output/firefox"
7
8
  require_relative "vernier/output/top"
@@ -9,135 +10,13 @@ require_relative "vernier/output/top"
9
10
  module Vernier
10
11
  class Error < StandardError; end
11
12
 
12
- class Result
13
- attr_reader :weights, :samples, :stack_table, :frame_table, :func_table
14
- attr_reader :timestamps, :sample_threads, :sample_categories
15
- attr_reader :markers
16
-
17
- attr_accessor :pid, :start_time, :end_time
18
- attr_accessor :threads
19
- attr_accessor :meta
20
-
21
- def started_at
22
- meta[:started_at]
23
- end
24
-
25
- def to_gecko
26
- Output::Firefox.new(self).output
27
- end
28
-
29
- def write(out:)
30
- File.write(out, to_gecko)
31
- end
32
-
33
- def each_sample
34
- return enum_for(__method__) unless block_given?
35
- @samples.size.times do |sample_idx|
36
- weight = @weights[sample_idx]
37
- stack_idx = @samples[sample_idx]
38
- yield stack(stack_idx), weight
39
- end
40
- end
41
-
42
- class BaseType
43
- attr_reader :result, :idx
44
- def initialize(result, idx)
45
- @result = result
46
- @idx = idx
47
- end
48
-
49
- def to_s
50
- idx.to_s
51
- end
52
-
53
- def inspect
54
- "#<#{self.class}\n#{to_s}>"
55
- end
56
- end
57
-
58
- class Func < BaseType
59
- def label
60
- result.func_table[:name][idx]
61
- end
62
- alias name label
63
-
64
- def filename
65
- result.func_table[:filename][idx]
66
- end
67
-
68
- def to_s
69
- "#{name} at #{filename}"
70
- end
71
- end
72
-
73
- class Frame < BaseType
74
- def label; func.label; end
75
- def filename; func.filename; end
76
- alias name label
77
-
78
- def func
79
- func_idx = result.frame_table[:func][idx]
80
- Func.new(result, func_idx)
81
- end
82
-
83
- def line
84
- result.frame_table[:line][idx]
85
- end
86
-
87
- def to_s
88
- "#{func}:#{line}"
89
- end
90
- end
91
-
92
- class Stack < BaseType
93
- def each_frame
94
- return enum_for(__method__) unless block_given?
95
-
96
- stack_idx = idx
97
- while stack_idx
98
- frame_idx = result.stack_table[:frame][stack_idx]
99
- yield Frame.new(result, frame_idx)
100
- stack_idx = result.stack_table[:parent][stack_idx]
101
- end
102
- end
103
-
104
- def leaf_frame_idx
105
- result.stack_table[:frame][idx]
106
- end
107
-
108
- def leaf_frame
109
- Frame.new(result, leaf_frame_idx)
110
- end
111
-
112
- def frames
113
- each_frame.to_a
114
- end
115
-
116
- def to_s
117
- arr = []
118
- each_frame do |frame|
119
- arr << frame.to_s
120
- end
121
- arr.join("\n")
122
- end
123
- end
124
-
125
- def stack(idx)
126
- Stack.new(self, idx)
127
- end
128
-
129
- def total_bytes
130
- @weights.sum
131
- end
132
- end
133
-
134
13
  def self.trace(mode: :wall, out: nil, interval: nil)
135
14
  collector = Vernier::Collector.new(mode, { interval: })
136
15
  collector.start
137
16
 
138
17
  result = nil
139
18
  begin
140
- yield
19
+ yield collector
141
20
  ensure
142
21
  result = collector.stop
143
22
  end
@@ -151,20 +30,14 @@ module Vernier
151
30
  def self.trace_retained(out: nil, gc: true)
152
31
  3.times { GC.start } if gc
153
32
 
154
- start_time = Process.clock_gettime(Process::CLOCK_REALTIME, :millisecond)
155
-
156
33
  collector = Vernier::Collector.new(:retained)
157
34
  collector.start
158
35
 
159
36
  result = nil
160
37
  begin
161
- yield
38
+ yield collector
162
39
  ensure
163
40
  result = collector.stop
164
- end_time = Process.clock_gettime(Process::CLOCK_REALTIME, :millisecond)
165
- result.pid = Process.pid
166
- result.start_time = start_time
167
- result.end_time = end_time
168
41
  end
169
42
 
170
43
  if out
metadata CHANGED
@@ -1,19 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vernier
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Hawthorn
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-08-04 00:00:00.000000000 Z
11
+ date: 2023-08-29 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: An experimental profiler
14
14
  email:
15
15
  - john@hawthorn.email
16
- executables: []
16
+ executables:
17
+ - vernier
17
18
  extensions:
18
19
  - ext/vernier/extconf.rb
19
20
  extra_rdoc_files: []
@@ -25,19 +26,24 @@ files:
25
26
  - Rakefile
26
27
  - bin/console
27
28
  - bin/setup
29
+ - bin/vernier
30
+ - examples/minitest.rb
31
+ - examples/ractor.rb
32
+ - examples/rails.rb
28
33
  - examples/threaded_http_requests.rb
34
+ - exe/vernier
29
35
  - ext/vernier/extconf.rb
30
36
  - ext/vernier/ruby_type_names.h
31
- - ext/vernier/stack.hh
32
37
  - ext/vernier/vernier.cc
33
38
  - ext/vernier/vernier.hh
34
39
  - lib/vernier.rb
40
+ - lib/vernier/autorun.rb
35
41
  - lib/vernier/collector.rb
36
42
  - lib/vernier/marker.rb
37
43
  - lib/vernier/output/firefox.rb
38
44
  - lib/vernier/output/top.rb
45
+ - lib/vernier/result.rb
39
46
  - lib/vernier/version.rb
40
- - sig/vernier.rbs
41
47
  - vernier.gemspec
42
48
  homepage: https://github.com/jhawthorn/vernier
43
49
  licenses:
data/ext/vernier/stack.hh DELETED
@@ -1,155 +0,0 @@
1
- #pragma once
2
-
3
- #include "ruby/debug.h"
4
-
5
- #include <iostream>
6
- #include <vector>
7
- #include <memory>
8
- #include <algorithm>
9
-
10
- struct FrameInfo {
11
- static const char *label_cstr(VALUE frame) {
12
- VALUE label = rb_profile_frame_full_label(frame);
13
- return StringValueCStr(label);
14
- }
15
-
16
- static const char *file_cstr(VALUE frame) {
17
- VALUE file = rb_profile_frame_absolute_path(frame);
18
- if (NIL_P(file))
19
- file = rb_profile_frame_path(frame);
20
- if (NIL_P(file)) {
21
- return "";
22
- } else {
23
- return StringValueCStr(file);
24
- }
25
- }
26
-
27
- static int first_lineno_int(VALUE frame) {
28
- VALUE first_lineno = rb_profile_frame_first_lineno(frame);
29
- return NIL_P(first_lineno) ? 0 : FIX2INT(first_lineno);
30
- }
31
-
32
- FrameInfo(VALUE frame) :
33
- label(label_cstr(frame)),
34
- file(file_cstr(frame)),
35
- first_lineno(first_lineno_int(frame)) { }
36
-
37
- std::string label;
38
- std::string file;
39
- int first_lineno;
40
- };
41
-
42
- bool operator==(const FrameInfo& lhs, const FrameInfo& rhs) noexcept {
43
- return
44
- lhs.label == rhs.label &&
45
- lhs.file == rhs.file &&
46
- lhs.first_lineno == rhs.first_lineno;
47
- }
48
-
49
- template<>
50
- struct std::hash<FrameInfo>
51
- {
52
- std::size_t operator()(FrameInfo const& f) const noexcept
53
- {
54
- return
55
- std::hash<std::string>{}(f.label) ^
56
- std::hash<std::string>{}(f.file) ^
57
- f.first_lineno;
58
- }
59
- };
60
-
61
-
62
- struct Frame {
63
- VALUE frame;
64
- int line;
65
-
66
- FrameInfo info() const {
67
- return FrameInfo(frame);
68
- }
69
- };
70
-
71
- bool operator==(const Frame& lhs, const Frame& rhs) noexcept {
72
- return lhs.frame == rhs.frame && lhs.line == rhs.line;
73
- }
74
-
75
- template<>
76
- struct std::hash<Frame>
77
- {
78
- std::size_t operator()(Frame const& s) const noexcept
79
- {
80
- return s.frame ^ s.line;
81
- }
82
- };
83
-
84
- struct BaseStack {
85
- virtual ~BaseStack() {};
86
-
87
- virtual int size() const = 0;
88
- };
89
-
90
- struct Stack : public BaseStack {
91
- std::unique_ptr<VALUE[]> frames;
92
- std::unique_ptr<int[]> lines;
93
- int _size = 0;
94
-
95
- int size() const {
96
- return _size;
97
- }
98
-
99
- Stack(const VALUE *_frames, const int *_lines, int size) :
100
- _size(size),
101
- frames(std::make_unique<VALUE[]>(size)),
102
- lines(std::make_unique<int[]>(size))
103
- {
104
- std::copy_n(_frames, size, &frames[0]);
105
- std::copy_n(_lines, size, &lines[0]);
106
- }
107
-
108
- Stack(const Stack &s) :
109
- _size(s.size()),
110
- frames(std::make_unique<VALUE[]>(s.size())),
111
- lines(std::make_unique<int[]>(s.size()))
112
- {
113
- std::copy_n(&s.frames[0], s.size(), &frames[0]);
114
- std::copy_n(&s.lines[0], s.size(), &lines[0]);
115
- }
116
-
117
- Frame frame(int i) const {
118
- if (i >= size()) throw std::out_of_range("nope");
119
- return Frame{frames[i], lines[i]};
120
- }
121
- };
122
-
123
- bool operator==(const Stack& lhs, const Stack& rhs) noexcept {
124
- return lhs.size() == rhs.size() &&
125
- std::equal(&lhs.frames[0], &lhs.frames[lhs.size()], &rhs.frames[0]) &&
126
- std::equal(&lhs.lines[0], &lhs.lines[lhs.size()], &rhs.lines[0]);
127
- }
128
-
129
- // https://xoshiro.di.unimi.it/splitmix64.c
130
- // https://nullprogram.com/blog/2018/07/31/
131
- uint64_t
132
- hash64(uint64_t x)
133
- {
134
- x ^= x >> 16;
135
- x *= 0x7feb352dU;
136
- x ^= x >> 15;
137
- x *= 0x846ca68bU;
138
- x ^= x >> 16;
139
- return x;
140
- }
141
-
142
- template<>
143
- struct std::hash<Stack>
144
- {
145
- std::size_t operator()(Stack const& s) const noexcept
146
- {
147
- size_t hash = 0;
148
- for (int i = 0; i < s.size(); i++) {
149
- VALUE frame = s.frames[i];
150
- hash ^= frame;
151
- hash = hash64(hash);
152
- }
153
- return hash;
154
- }
155
- };
data/sig/vernier.rbs DELETED
@@ -1,4 +0,0 @@
1
- module Vernier
2
- VERSION: String
3
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
- end