fiber-profiler 0.1.1 → 0.1.3

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: cb42b05548bfd94568a8ed386f637d62fc55a8a86327647c5f397fc57c7cbee7
4
- data.tar.gz: 929e61a6392395e02eaedab0c7ed888a0dca4d73139eea138b065807a80a4191
3
+ metadata.gz: a2bbdd5d629b193bb2c9fe87a9935abda45b21339bc9fa8e9a177a3cb08c6ca4
4
+ data.tar.gz: c38ff2d79d1dcc2cef0745923da73c0e1bfda612623d1592fffbeb708d6ff97f
5
5
  SHA512:
6
- metadata.gz: 196980ad2d5d0cc53d159624c461a6cbf01adbc8cb822a79eaf38d58c168b26a88de05be131a57e454be2cf8b1258be548e37e6f3bcb7c0e67ddab73cef71e81
7
- data.tar.gz: fa008843a3fe2fc972d3edd1070678889003352e4d57827e4e79e87312376ad4e7bf1e81041c166bed4d6121ca50b0fc3eb7dcb1d81e8f9968a7b4303d52b96e
6
+ metadata.gz: a23c926af43a1db2f2cf71b269bbb63d0bff602ca17b40ced3da152dd317d084c2f41f47c42ba7194a7be67df6be8d17de54a829808a82173bb3dc83303b14bd
7
+ data.tar.gz: afd379c5f799fda50fa7229f4512ff01297e9f7f66a32d0eaab575a77c3b66d9b7cc1d13627609193983173b725b8851bf9240ab8096881bc764b66ba83b9a73
checksums.yaml.gz.sig CHANGED
Binary file
@@ -73,12 +73,14 @@ struct Fiber_Profiler_Capture {
73
73
  // Calls that are shorter than this filter threshold will be ignored:
74
74
  double filter_threshold;
75
75
 
76
+ // Output handling:
76
77
  VALUE output;
77
78
  Fiber_Profiler_Stream_Print print;
78
79
  struct Fiber_Profiler_Stream stream;
79
80
 
80
81
  // Whether or not the profiler is currently running:
81
82
  int running;
83
+ VALUE thread;
82
84
 
83
85
  // Whether or not to capture call data:
84
86
  int capture;
@@ -133,6 +135,7 @@ void Fiber_Profiler_Capture_Call_free(void *element) {
133
135
  static void Fiber_Profiler_Capture_mark(void *ptr) {
134
136
  struct Fiber_Profiler_Capture *profiler = (struct Fiber_Profiler_Capture*)ptr;
135
137
 
138
+ rb_gc_mark_movable(profiler->thread);
136
139
  rb_gc_mark_movable(profiler->output);
137
140
 
138
141
  // If `klass` is stored as a VALUE in calls, we need to mark them here:
@@ -144,6 +147,7 @@ static void Fiber_Profiler_Capture_mark(void *ptr) {
144
147
  static void Fiber_Profiler_Capture_compact(void *ptr) {
145
148
  struct Fiber_Profiler_Capture *profiler = (struct Fiber_Profiler_Capture*)ptr;
146
149
 
150
+ profiler->thread = rb_gc_location(profiler->thread);
147
151
  profiler->output = rb_gc_location(profiler->output);
148
152
 
149
153
  // If `klass` is stored as a VALUE in calls, we need to update their locations here:
@@ -211,10 +215,12 @@ VALUE Fiber_Profiler_Capture_allocate(VALUE klass) {
211
215
  struct Fiber_Profiler_Capture *profiler = ALLOC(struct Fiber_Profiler_Capture);
212
216
 
213
217
  // Initialize the profiler state:
214
- Fiber_Profiler_Capture_output_set(profiler, rb_stderr);
215
218
  Fiber_Profiler_Stream_initialize(&profiler->stream);
219
+ profiler->output = Qnil;
216
220
 
217
221
  profiler->running = 0;
222
+ profiler->thread = Qnil;
223
+
218
224
  profiler->capture = 0;
219
225
  profiler->stalls = 0;
220
226
  profiler->nesting = 0;
@@ -258,6 +264,9 @@ VALUE Fiber_Profiler_Capture_initialize(int argc, VALUE *argv, VALUE self) {
258
264
 
259
265
  if (arguments[3] != Qundef) {
260
266
  Fiber_Profiler_Capture_output_set(profiler, arguments[3]);
267
+ } else {
268
+ // Initialize the profiler output - we dup `rb_stderr` because the profiler may otherwise run into synchronization issues with other uses of `rb_stderr`:
269
+ Fiber_Profiler_Capture_output_set(profiler, rb_obj_dup(rb_stderr));
261
270
  }
262
271
 
263
272
  return self;
@@ -324,16 +333,9 @@ static struct Fiber_Profiler_Capture_Call* profiler_event_record_call(struct Fib
324
333
  return call;
325
334
  }
326
335
 
327
- void Fiber_Profiler_Capture_fiber_switch(struct Fiber_Profiler_Capture *profiler);
328
-
329
336
  static void Fiber_Profiler_Capture_callback(rb_event_flag_t event_flag, VALUE data, VALUE self, ID id, VALUE klass) {
330
337
  struct Fiber_Profiler_Capture *profiler = Fiber_Profiler_Capture_get(data);
331
338
 
332
- if (event_flag & RUBY_EVENT_FIBER_SWITCH) {
333
- Fiber_Profiler_Capture_fiber_switch(profiler);
334
- return;
335
- }
336
-
337
339
  // We don't want to capture data if we're not running:
338
340
  if (!profiler->capture) return;
339
341
 
@@ -373,17 +375,24 @@ static void Fiber_Profiler_Capture_callback(rb_event_flag_t event_flag, VALUE da
373
375
  }
374
376
  }
375
377
 
376
- VALUE Fiber_Profiler_Capture_start(VALUE self) {
378
+ void Fiber_Profiler_Capture_pause(VALUE self) {
377
379
  struct Fiber_Profiler_Capture *profiler = Fiber_Profiler_Capture_get(self);
378
380
 
379
- if (profiler->running) return Qfalse;
381
+ if (!profiler->capture) return;
380
382
 
381
- profiler->running = 1;
383
+ profiler->capture = 0;
382
384
 
383
- Fiber_Profiler_Capture_reset(profiler);
384
- Fiber_Profiler_Time_current(&profiler->start_time);
385
+ rb_thread_remove_event_hook_with_data(profiler->thread, Fiber_Profiler_Capture_callback, self);
386
+ }
387
+
388
+ void Fiber_Profiler_Capture_resume(VALUE self) {
389
+ struct Fiber_Profiler_Capture *profiler = Fiber_Profiler_Capture_get(self);
385
390
 
386
- rb_event_flag_t event_flags = RUBY_EVENT_FIBER_SWITCH;
391
+ if (profiler->capture) return;
392
+
393
+ profiler->capture = 1;
394
+
395
+ rb_event_flag_t event_flags = 0;
387
396
 
388
397
  if (profiler->track_calls) {
389
398
  event_flags |= RUBY_EVENT_CALL | RUBY_EVENT_RETURN;
@@ -391,12 +400,29 @@ VALUE Fiber_Profiler_Capture_start(VALUE self) {
391
400
  // event_flags |= RUBY_EVENT_B_CALL | RUBY_EVENT_B_RETURN;
392
401
  }
393
402
 
394
- VALUE thread = rb_thread_current();
395
- rb_thread_add_event_hook(thread, Fiber_Profiler_Capture_callback, event_flags, self);
403
+ // CRuby will raise an exception if you try to add "INTERNAL_EVENT" hooks at the same time as other hooks, so we do it in two calls:
404
+ rb_thread_add_event_hook(profiler->thread, Fiber_Profiler_Capture_callback, event_flags, self);
405
+ rb_thread_add_event_hook(profiler->thread, Fiber_Profiler_Capture_callback, RUBY_INTERNAL_EVENT_GC_START | RUBY_INTERNAL_EVENT_GC_END_SWEEP, self);
406
+ }
407
+
408
+ void Fiber_Profiler_Capture_fiber_switch(VALUE self);
409
+
410
+ void Fiber_Profiler_Capture_fiber_switch_callback(rb_event_flag_t event_flag, VALUE data, VALUE self, ID id, VALUE klass) {
411
+ Fiber_Profiler_Capture_fiber_switch(data);
412
+ }
413
+
414
+ VALUE Fiber_Profiler_Capture_start(VALUE self) {
415
+ struct Fiber_Profiler_Capture *profiler = Fiber_Profiler_Capture_get(self);
416
+
417
+ if (profiler->running) return Qfalse;
418
+
419
+ profiler->running = 1;
420
+ profiler->thread = rb_thread_current();
421
+
422
+ Fiber_Profiler_Capture_reset(profiler);
423
+ Fiber_Profiler_Time_current(&profiler->start_time);
396
424
 
397
- // if (profiler->track_garbage_collection) {
398
- rb_thread_add_event_hook(thread, Fiber_Profiler_Capture_callback, RUBY_INTERNAL_EVENT_GC_START | RUBY_INTERNAL_EVENT_GC_END_SWEEP, self);
399
- // }
425
+ rb_thread_add_event_hook(profiler->thread, Fiber_Profiler_Capture_fiber_switch_callback, RUBY_EVENT_FIBER_SWITCH, self);
400
426
 
401
427
  return self;
402
428
  }
@@ -406,11 +432,13 @@ VALUE Fiber_Profiler_Capture_stop(VALUE self) {
406
432
 
407
433
  if (!profiler->running) return Qfalse;
408
434
 
409
- profiler->running = 0;
435
+ Fiber_Profiler_Capture_pause(self);
410
436
 
411
- VALUE thread = rb_thread_current();
412
- rb_thread_remove_event_hook_with_data(thread, Fiber_Profiler_Capture_callback, self);
437
+ rb_thread_remove_event_hook_with_data(profiler->thread, Fiber_Profiler_Capture_fiber_switch_callback, self);
413
438
 
439
+ profiler->running = 0;
440
+ profiler->thread = Qnil;
441
+
414
442
  Fiber_Profiler_Time_current(&profiler->stop_time);
415
443
  Fiber_Profiler_Capture_reset(profiler);
416
444
 
@@ -452,26 +480,29 @@ int Fiber_Profiler_Capture_sample(struct Fiber_Profiler_Capture *profiler) {
452
480
  }
453
481
  }
454
482
 
455
- void Fiber_Profiler_Capture_fiber_switch(struct Fiber_Profiler_Capture *profiler)
483
+ void Fiber_Profiler_Capture_fiber_switch(VALUE self)
456
484
  {
485
+ struct Fiber_Profiler_Capture *profiler = Fiber_Profiler_Capture_get(self);
457
486
  float duration = Fiber_Profiler_Capture_duration(profiler);
458
487
 
459
488
  if (profiler->capture) {
489
+ Fiber_Profiler_Capture_pause(self);
490
+
460
491
  Fiber_Profiler_Capture_finish(profiler);
461
492
 
462
493
  if (duration > profiler->stall_threshold) {
463
494
  profiler->stalls += 1;
464
495
  Fiber_Profiler_Capture_print(profiler);
465
496
  }
497
+
498
+ Fiber_Profiler_Capture_reset(profiler);
466
499
  }
467
500
 
468
- Fiber_Profiler_Capture_reset(profiler);
469
-
470
501
  if (Fiber_Profiler_Capture_sample(profiler)) {
471
502
  // Reset the start time:
472
503
  Fiber_Profiler_Time_current(&profiler->start_time);
473
504
 
474
- profiler->capture = 1;
505
+ Fiber_Profiler_Capture_resume(self);
475
506
  }
476
507
  }
477
508
 
@@ -560,6 +591,8 @@ void Fiber_Profiler_Capture_print_json(struct Fiber_Profiler_Capture *profiler,
560
591
  }
561
592
 
562
593
  void Fiber_Profiler_Capture_print(struct Fiber_Profiler_Capture *profiler) {
594
+ if (profiler->output == Qnil) return;
595
+
563
596
  FILE *stream = profiler->stream.file;
564
597
  profiler->print(profiler, stream);
565
598
  fflush(stream);
@@ -7,6 +7,6 @@
7
7
  class Fiber
8
8
  # @namespace
9
9
  module Profiler
10
- VERSION = "0.1.1"
10
+ VERSION = "0.1.3"
11
11
  end
12
12
  end
data/readme.md CHANGED
@@ -18,6 +18,10 @@ Please see the [project documentation](https://socketry.github.io/fiber-profiler
18
18
 
19
19
  Please see the [project releases](https://socketry.github.io/fiber-profiler/releases/index) for all releases.
20
20
 
21
+ ### v0.1.3
22
+
23
+ - Improved performance when not profiling (when sampling is enabled).
24
+
21
25
  ### v0.1.0
22
26
 
23
27
  - Initial implementation extracted from `io-event` gem.
data/releases.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Releases
2
2
 
3
+ ## v0.1.3
4
+
5
+ - Improved performance when not profiling (when sampling is enabled).
6
+
3
7
  ## v0.1.0
4
8
 
5
9
  - Initial implementation extracted from `io-event` gem.
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fiber-profiler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -36,7 +36,7 @@ cert_chain:
36
36
  Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
37
37
  voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
38
38
  -----END CERTIFICATE-----
39
- date: 2025-02-13 00:00:00.000000000 Z
39
+ date: 2025-02-14 00:00:00.000000000 Z
40
40
  dependencies: []
41
41
  executables: []
42
42
  extensions:
metadata.gz.sig CHANGED
Binary file