vernier 0.3.0 → 0.3.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 +4 -4
- data/README.md +24 -8
- data/ext/vernier/vernier.cc +13 -7
- data/lib/vernier/output/firefox.rb +4 -6
- data/lib/vernier/version.rb +1 -1
- data/lib/vernier.rb +3 -3
- data/vernier.gemspec +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6050bca74116d0e90f98025fe23d7fbd40c6107c085e3f768d606d4f418ebc60
|
4
|
+
data.tar.gz: e302542d8b06852d28d0ec1e2528f23bba46d5ef9ea9a828c9dbcdb985a292a3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d20e5f9d9c894a253bc4aeb6b9da6cb35d916e881abedf996ce19757a9cd92efe43bcc76fda0aa4ce5e334be36582adf7c716a998c4c5e1f403dc57364fb5ab
|
7
|
+
data.tar.gz: 7cf03df7bcb4f961b5b456eb781fd5818de7e18501baa01592ce17528f5eae7b272e90dcff200f861495ebb1a83c87f9146306db66ce20a9d56467ab87bce3c6
|
data/README.md
CHANGED
@@ -1,6 +1,22 @@
|
|
1
1
|
# Vernier
|
2
2
|
|
3
|
-
|
3
|
+
Next-generation Ruby sampling profiler. Tracks multiple threads, GVL activity, GC pauses, idle time, and more.
|
4
|
+
|
5
|
+
## Examples
|
6
|
+
|
7
|
+
[Livestreamed demo: Pairin' with Aaron (YouTube)](https://www.youtube.com/watch?v=9nvX3OHykGQ#t=27m43)
|
8
|
+
|
9
|
+
Sidekiq jobs from Mastodon (time, threded)
|
10
|
+
: https://share.firefox.dev/44jZRf3
|
11
|
+
|
12
|
+
Puma web requests from Mastodon (time, threded)
|
13
|
+
: https://share.firefox.dev/48FOTnF
|
14
|
+
|
15
|
+
Rails benchmark - lobste.rs (time)
|
16
|
+
: https://share.firefox.dev/3Ld89id
|
17
|
+
|
18
|
+
`require "irb"` (retained memory)
|
19
|
+
: https://share.firefox.dev/3DhLsFa
|
4
20
|
|
5
21
|
## Installation
|
6
22
|
|
@@ -10,24 +26,24 @@ gem 'vernier'
|
|
10
26
|
|
11
27
|
## Usage
|
12
28
|
|
13
|
-
### Retained memory
|
14
29
|
|
15
|
-
|
30
|
+
### Time
|
16
31
|
|
17
32
|
```
|
18
|
-
|
33
|
+
Vernier.trace(out: "time_profile.json") { some_slow_method }
|
19
34
|
```
|
20
35
|
|
21
|
-
The output can then be viewed in the
|
36
|
+
The output can then be viewed in the Firefox Profiler (demo) or the [`profile-viewer` gem](https://github.com/tenderlove/profiler/tree/ruby) (a Ruby-customized version of the firefox profiler.
|
22
37
|
|
23
|
-
|
38
|
+
### Retained memory
|
24
39
|
|
25
|
-
|
40
|
+
Record a flamegraph of all **retained** allocations from loading `irb`.
|
26
41
|
|
27
42
|
```
|
28
|
-
Vernier.
|
43
|
+
ruby -r vernier -e 'Vernier.trace_retained(out: "irb_profile.json") { require "irb" }'
|
29
44
|
```
|
30
45
|
|
46
|
+
|
31
47
|
## Development
|
32
48
|
|
33
49
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/ext/vernier/vernier.cc
CHANGED
@@ -72,13 +72,17 @@ class TimeStamp {
|
|
72
72
|
return TimeStamp(0);
|
73
73
|
}
|
74
74
|
|
75
|
-
|
76
|
-
|
75
|
+
// SleepUntil a specified timestamp
|
76
|
+
// Highly accurate manual sleep time
|
77
|
+
static void SleepUntil(const TimeStamp &target_time) {
|
78
|
+
if (target_time.zero()) return;
|
79
|
+
struct timespec ts = target_time.timespec();
|
77
80
|
|
78
81
|
int res;
|
79
82
|
do {
|
80
|
-
|
81
|
-
|
83
|
+
// do nothing until it's time :)
|
84
|
+
sleep(0);
|
85
|
+
} while (target_time > TimeStamp::Now());
|
82
86
|
}
|
83
87
|
|
84
88
|
static TimeStamp from_microseconds(uint64_t us) {
|
@@ -1091,6 +1095,9 @@ class RetainedCollector : public BaseCollector {
|
|
1091
1095
|
VALUE weights = rb_ary_new();
|
1092
1096
|
rb_hash_aset(thread_hash, sym("weights"), weights);
|
1093
1097
|
|
1098
|
+
rb_hash_aset(thread_hash, sym("name"), rb_str_new_cstr("retained memory"));
|
1099
|
+
rb_hash_aset(thread_hash, sym("started_at"), ULL2NUM(collector->started_at.nanoseconds()));
|
1100
|
+
|
1094
1101
|
for (auto& obj: collector->object_list) {
|
1095
1102
|
const auto search = collector->object_frames.find(obj);
|
1096
1103
|
if (search != collector->object_frames.end()) {
|
@@ -1252,13 +1259,12 @@ class TimeCollector : public BaseCollector {
|
|
1252
1259
|
|
1253
1260
|
next_sample_schedule += interval;
|
1254
1261
|
|
1262
|
+
// If sampling falls behind, restart, and check in another interval
|
1255
1263
|
if (next_sample_schedule < sample_complete) {
|
1256
|
-
//fprintf(stderr, "fell behind by %ius\n", (sample_complete - next_sample_schedule).microseconds());
|
1257
1264
|
next_sample_schedule = sample_complete + interval;
|
1258
1265
|
}
|
1259
1266
|
|
1260
|
-
TimeStamp
|
1261
|
-
TimeStamp::Sleep(sleep_time);
|
1267
|
+
TimeStamp::SleepUntil(next_sample_schedule);
|
1262
1268
|
}
|
1263
1269
|
|
1264
1270
|
thread_stopped.post();
|
@@ -157,14 +157,15 @@ module Vernier
|
|
157
157
|
class Thread
|
158
158
|
attr_reader :profile
|
159
159
|
|
160
|
-
def initialize(profile, categorizer, name:, tid:, samples:, weights:, timestamps
|
160
|
+
def initialize(profile, categorizer, name:, tid:, samples:, weights:, timestamps: nil, sample_categories: nil, markers:, started_at:, stopped_at: nil)
|
161
161
|
@profile = profile
|
162
162
|
@categorizer = categorizer
|
163
163
|
@tid = tid
|
164
164
|
@name = name
|
165
165
|
|
166
|
+
timestamps ||= [0] * samples.size
|
166
167
|
@samples, @weights, @timestamps = samples, weights, timestamps
|
167
|
-
@sample_categories = sample_categories
|
168
|
+
@sample_categories = sample_categories || ([0] * samples.size)
|
168
169
|
@markers = markers
|
169
170
|
|
170
171
|
@started_at, @stopped_at = started_at, stopped_at
|
@@ -211,7 +212,7 @@ module Vernier
|
|
211
212
|
def data
|
212
213
|
{
|
213
214
|
name: @name,
|
214
|
-
isMainThread: @tid == ::Thread.main.native_thread_id,
|
215
|
+
isMainThread: (@tid == ::Thread.main.native_thread_id) || (profile.threads.size == 1),
|
215
216
|
processStartupTime: 0, # FIXME
|
216
217
|
processShutdownTime: nil, # FIXME
|
217
218
|
registerTime: (@started_at - 0) / 1_000_000.0,
|
@@ -237,8 +238,6 @@ module Vernier
|
|
237
238
|
end
|
238
239
|
|
239
240
|
def markers_table
|
240
|
-
size = @markers.size
|
241
|
-
|
242
241
|
string_indexes = []
|
243
242
|
start_times = []
|
244
243
|
end_times = []
|
@@ -292,7 +291,6 @@ module Vernier
|
|
292
291
|
times = (0...size).to_a
|
293
292
|
end
|
294
293
|
|
295
|
-
raise unless samples.size == size
|
296
294
|
raise unless weights.size == size
|
297
295
|
raise unless times.size == size
|
298
296
|
|
data/lib/vernier/version.rb
CHANGED
data/lib/vernier.rb
CHANGED
@@ -19,11 +19,11 @@ module Vernier
|
|
19
19
|
yield collector
|
20
20
|
ensure
|
21
21
|
result = collector.stop
|
22
|
+
if out
|
23
|
+
File.write(out, Output::Firefox.new(result).output)
|
24
|
+
end
|
22
25
|
end
|
23
26
|
|
24
|
-
if out
|
25
|
-
File.write(out, Output::Firefox.new(result).output)
|
26
|
-
end
|
27
27
|
result
|
28
28
|
end
|
29
29
|
|
data/vernier.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
|
|
12
12
|
spec.description = spec.summary
|
13
13
|
spec.homepage = "https://github.com/jhawthorn/vernier"
|
14
14
|
spec.license = "MIT"
|
15
|
-
spec.required_ruby_version = ">= 3.2.
|
15
|
+
spec.required_ruby_version = ">= 3.2.1"
|
16
16
|
|
17
17
|
spec.metadata["homepage_uri"] = spec.homepage
|
18
18
|
spec.metadata["source_code_uri"] = spec.homepage
|
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.3.
|
4
|
+
version: 0.3.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-
|
11
|
+
date: 2023-12-05 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: An experimental profiler
|
14
14
|
email:
|
@@ -60,7 +60,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
60
60
|
requirements:
|
61
61
|
- - ">="
|
62
62
|
- !ruby/object:Gem::Version
|
63
|
-
version: 3.2.
|
63
|
+
version: 3.2.1
|
64
64
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - ">="
|