vernier 0.3.0 → 0.3.1

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: 52f738e495accaaab1af3f33a806a7b20467aa8f2a93f4b7bf8d7300fdaf88ad
4
- data.tar.gz: e6877e7315fb990e8db9482b940a96068770987989fec85a804c75ce79b62022
3
+ metadata.gz: 6050bca74116d0e90f98025fe23d7fbd40c6107c085e3f768d606d4f418ebc60
4
+ data.tar.gz: e302542d8b06852d28d0ec1e2528f23bba46d5ef9ea9a828c9dbcdb985a292a3
5
5
  SHA512:
6
- metadata.gz: 4dcf1c2ebcbfcfd1b5a456fbc9ffbfd82da1f96622b8dc889d9ece105a9f461768dd688b6e0ee73102db104bff527a9c940f6d74689d520005ea216823444cbe
7
- data.tar.gz: 97e0116ec7de5ee084512520debd37d0262555ca6a09d427b9147c3e08303492c925e8b1f81c9299915aff6322122a82e8737d1ef22823da8689aab2ce63aa6f
6
+ metadata.gz: 9d20e5f9d9c894a253bc4aeb6b9da6cb35d916e881abedf996ce19757a9cd92efe43bcc76fda0aa4ce5e334be36582adf7c716a998c4c5e1f403dc57364fb5ab
7
+ data.tar.gz: 7cf03df7bcb4f961b5b456eb781fd5818de7e18501baa01592ce17528f5eae7b272e90dcff200f861495ebb1a83c87f9146306db66ce20a9d56467ab87bce3c6
data/README.md CHANGED
@@ -1,6 +1,22 @@
1
1
  # Vernier
2
2
 
3
- Experimental next-generation Ruby sampling profiler. Tracks multiple threads, GVL activity, GC pauses, idle time, and more.
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
- Record a flamegraph of all **retained** allocations from loading `irb`.
30
+ ### Time
16
31
 
17
32
  ```
18
- ruby -r vernier -e 'Vernier.trace_retained(out: "irb_profile.json") { require "irb" }'
33
+ Vernier.trace(out: "time_profile.json") { some_slow_method }
19
34
  ```
20
35
 
21
- The output can then be viewed in the [Firefox Profiler (demo)](https://share.firefox.dev/3DhLsFa) or the [`profile-viewer` gem](https://github.com/tenderlove/profiler/tree/ruby) (a Ruby-customized version of the firefox profiler.
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
- ![Screenshot 2023-07-16 at 21-06-19 Ruby_Vernier – 1970-01-01 12 00 00 a m UTC – Firefox Profiler](https://github.com/jhawthorn/vernier/assets/131752/9ca0b593-70fb-4c8b-aed9-cb33e0e0bc06)
38
+ ### Retained memory
24
39
 
25
- ### Time
40
+ Record a flamegraph of all **retained** allocations from loading `irb`.
26
41
 
27
42
  ```
28
- Vernier.trace(out: "time_profile.json") { some_slow_method }
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.
@@ -72,13 +72,17 @@ class TimeStamp {
72
72
  return TimeStamp(0);
73
73
  }
74
74
 
75
- static void Sleep(const TimeStamp &time) {
76
- struct timespec ts = time.timespec();
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
- res = nanosleep(&ts, &ts);
81
- } while (res && errno == EINTR);
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 sleep_time = next_sample_schedule - sample_complete;
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:, sample_categories:, markers:, started_at:, stopped_at: nil)
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
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Vernier
4
- VERSION = "0.3.0"
4
+ VERSION = "0.3.1"
5
5
  end
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.0"
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.0
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-08-29 00:00:00.000000000 Z
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.0
63
+ version: 3.2.1
64
64
  required_rubygems_version: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ">="