fiber-profiler 0.1.1 → 0.1.3

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: 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