vernier 0.2.0 → 0.2.1

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: da6d8fafb453c25b5f1127a33c53401150cb91bf604a37db971c952ec490d900
4
- data.tar.gz: 97cc5b3435335fe97c531122d5692a3af3264c5abeb34eafb1a1808743b017fe
3
+ metadata.gz: dcfae18cfffd67e1e8a52c0c9de2654e7523b674d492964dfa3447c967d981e3
4
+ data.tar.gz: 4ff2a81a37d19f974914a0ff3fa28937302a636721b8732f7e7b282f895db9f3
5
5
  SHA512:
6
- metadata.gz: 92529d7331c8a015c900227f1d28b093322dfb386ce99213c4a22dea168d433f9e0d9ae221c3171ea7e3c91fd67753a9da668140af97f62e0edec08341cb4f63
7
- data.tar.gz: bdd0baaf24abdbed97f603da42e827fa10442f4f702f15a5ee2f01e2b25eb893465d8b313bcd3dec84a402d76554aa58d28547e2bad401db2c4dbb24797a2414
6
+ metadata.gz: bd4e4f001047bb3f20c9c0670339747b9e29abf6e44bcd77dbb38fcf7c16f42d33eef893045ab7a899b155d9b98765950e91af79864234a2d66243490d367d49
7
+ data.tar.gz: 14cecc8aa1058b4e38f130bed6ec1d43e8a59a636c125862ef6c61df13f885e1d76b1a142d0fa8fab16ea6bfee2642b7cd606bb562020f800ce3518b2c7fac2c
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "mkmf"
4
4
 
5
- $CXXFLAGS += " -std=c++17 "
5
+ $CXXFLAGS += " -std=c++14 "
6
6
  $CXXFLAGS += " -ggdb3 -Og "
7
7
 
8
8
  create_makefile("vernier/vernier")
@@ -9,18 +9,19 @@
9
9
  #include <cassert>
10
10
  #include <atomic>
11
11
  #include <mutex>
12
- #include <optional>
13
12
 
14
13
  #include <sys/time.h>
15
14
  #include <signal.h>
16
15
  #ifdef __APPLE__
16
+ /* macOS */
17
17
  #include <dispatch/dispatch.h>
18
18
  #else
19
+ /* Linux */
19
20
  #include <semaphore.h>
21
+ #include <sys/syscall.h> /* for SYS_gettid */
20
22
  #endif
21
23
 
22
24
  #include "vernier.hh"
23
- #include "stack.hh"
24
25
 
25
26
  #include "ruby/ruby.h"
26
27
  #include "ruby/debug.h"
@@ -149,6 +150,69 @@ std::ostream& operator<<(std::ostream& os, const TimeStamp& info) {
149
150
  return os;
150
151
  }
151
152
 
153
+ struct FrameInfo {
154
+ static const char *label_cstr(VALUE frame) {
155
+ VALUE label = rb_profile_frame_full_label(frame);
156
+ return StringValueCStr(label);
157
+ }
158
+
159
+ static const char *file_cstr(VALUE frame) {
160
+ VALUE file = rb_profile_frame_absolute_path(frame);
161
+ if (NIL_P(file))
162
+ file = rb_profile_frame_path(frame);
163
+ if (NIL_P(file)) {
164
+ return "";
165
+ } else {
166
+ return StringValueCStr(file);
167
+ }
168
+ }
169
+
170
+ static int first_lineno_int(VALUE frame) {
171
+ VALUE first_lineno = rb_profile_frame_first_lineno(frame);
172
+ return NIL_P(first_lineno) ? 0 : FIX2INT(first_lineno);
173
+ }
174
+
175
+ FrameInfo(VALUE frame) :
176
+ label(label_cstr(frame)),
177
+ file(file_cstr(frame)),
178
+ first_lineno(first_lineno_int(frame)) { }
179
+
180
+ std::string label;
181
+ std::string file;
182
+ int first_lineno;
183
+ };
184
+
185
+ bool operator==(const FrameInfo& lhs, const FrameInfo& rhs) noexcept {
186
+ return
187
+ lhs.label == rhs.label &&
188
+ lhs.file == rhs.file &&
189
+ lhs.first_lineno == rhs.first_lineno;
190
+ }
191
+
192
+ struct Frame {
193
+ VALUE frame;
194
+ int line;
195
+
196
+ FrameInfo info() const {
197
+ return FrameInfo(frame);
198
+ }
199
+ };
200
+
201
+ bool operator==(const Frame& lhs, const Frame& rhs) noexcept {
202
+ return lhs.frame == rhs.frame && lhs.line == rhs.line;
203
+ }
204
+
205
+ namespace std {
206
+ template<>
207
+ struct hash<Frame>
208
+ {
209
+ std::size_t operator()(Frame const& s) const noexcept
210
+ {
211
+ return s.frame ^ s.line;
212
+ }
213
+ };
214
+ }
215
+
152
216
  // A basic semaphore built on sem_wait/sem_post
153
217
  // post() is guaranteed to be async-signal-safe
154
218
  class SamplerSemaphore {
@@ -459,6 +523,8 @@ class BaseCollector {
459
523
  bool running = false;
460
524
  FrameList frame_list;
461
525
 
526
+ virtual ~BaseCollector() {}
527
+
462
528
  virtual bool start() {
463
529
  if (running) {
464
530
  return false;
@@ -666,7 +732,9 @@ class Thread {
666
732
  if (e != 0) rb_syserr_fail(e, "pthread_threadid_np");
667
733
  return thread_id;
668
734
  #else
669
- return gettid();
735
+ // gettid() is only available as of glibc 2.30
736
+ pid_t tid = syscall(SYS_gettid);
737
+ return tid;
670
738
  #endif
671
739
  }
672
740
 
@@ -817,7 +885,7 @@ class TimeCollector : public BaseCollector {
817
885
  atomic_bool running;
818
886
  SamplerSemaphore thread_stopped;
819
887
 
820
- static inline LiveSample *live_sample;
888
+ static LiveSample *live_sample;
821
889
 
822
890
  TimeStamp started_at;
823
891
  TimeStamp interval;
@@ -1097,6 +1165,8 @@ class TimeCollector : public BaseCollector {
1097
1165
  }
1098
1166
  };
1099
1167
 
1168
+ LiveSample *TimeCollector::live_sample;
1169
+
1100
1170
  static void
1101
1171
  collector_mark(void *data) {
1102
1172
  BaseCollector *collector = static_cast<BaseCollector *>(data);
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Vernier
4
- VERSION = "0.2.0"
4
+ VERSION = "0.2.1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
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.2.1
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-08 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: An experimental profiler
14
14
  email:
@@ -28,7 +28,6 @@ files:
28
28
  - examples/threaded_http_requests.rb
29
29
  - ext/vernier/extconf.rb
30
30
  - ext/vernier/ruby_type_names.h
31
- - ext/vernier/stack.hh
32
31
  - ext/vernier/vernier.cc
33
32
  - ext/vernier/vernier.hh
34
33
  - lib/vernier.rb
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
- };