fiber-profiler 0.5.0 → 0.6.0
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
- checksums.yaml.gz.sig +0 -0
- data/bake/fiber/profiler/analyze.rb +26 -0
- data/context/getting-started.md +72 -0
- data/context/index.yaml +11 -0
- data/ext/fiber/profiler/capture.c +0 -2
- data/lib/fiber/profiler/capture.rb +39 -1
- data/lib/fiber/profiler/fork_handler.rb +33 -0
- data/lib/fiber/profiler/version.rb +1 -1
- data/lib/fiber/profiler.rb +2 -1
- data/license.md +1 -1
- data/readme.md +20 -0
- data/releases.md +4 -0
- data.tar.gz.sig +3 -2
- metadata +7 -3
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4eb8511c2bd355496fcb3461944f5fc7881795e7e44d13f4a59497689feaa838
|
|
4
|
+
data.tar.gz: 5146ceedbb0f9fc2230b5c3f50b1c0fac9ef2b424078ced732051b6e7e303431
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 427ddb031dc285d0c45c7c1dc72e0793c200b216ca3854272d675ad2cf677c58bf5a7a07bdaf043890f583527fe32ec263b0e12cf53ac11e95a90921e6576013
|
|
7
|
+
data.tar.gz: 625fe37c351399c0c1a5588f2577238899b2cad5b3b876d2e4fbe7c76ffdd26865c31111d68c09e04160a369cb0ca149e9c2eb97e1417dacdb7247a5a6b06861
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2025, by Samuel Williams.
|
|
5
|
+
|
|
6
|
+
# @parameter input [Input] The input to process.
|
|
7
|
+
def analyze(input:)
|
|
8
|
+
summary = {}
|
|
9
|
+
|
|
10
|
+
input.each do |sample|
|
|
11
|
+
duration = sample["duration"]
|
|
12
|
+
calls = sample["calls"]
|
|
13
|
+
|
|
14
|
+
if duration and calls
|
|
15
|
+
calls.each do |call|
|
|
16
|
+
location = "#{call["path"]}:#{call["line"]}"
|
|
17
|
+
|
|
18
|
+
summary[location] ||= {duration: 0, calls: 0, class: call["class"], method: call["method"]}
|
|
19
|
+
summary[location][:duration] += call["duration"]
|
|
20
|
+
summary[location][:calls] += 1
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
summary.sort_by{|location, data| -data[:duration]}
|
|
26
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Getting Started
|
|
2
|
+
|
|
3
|
+
This guide explains how to detect stalls using the fiber profiler.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add the gem to your project:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
$ bundle add fiber-profiler
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
Instrument your code using the default profiler:
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
#!/usr/bin/env ruby
|
|
19
|
+
|
|
20
|
+
require "fiber/profiler"
|
|
21
|
+
|
|
22
|
+
profiler = Fiber::Profiler.default
|
|
23
|
+
|
|
24
|
+
profiler&.start
|
|
25
|
+
|
|
26
|
+
# Your application code:
|
|
27
|
+
Fiber.new do
|
|
28
|
+
sleep 0.1
|
|
29
|
+
end.resume
|
|
30
|
+
|
|
31
|
+
profiler&.stop
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Running this program will output the following:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
$ FIBER_PROFILER_CAPTURE=true bundle exec ./test.rb
|
|
38
|
+
Fiber stalled for 0.105 seconds
|
|
39
|
+
/Users/samuel/Developer/socketry/fiber-profiler/test.rb:11 in c-call 'Kernel#sleep' (0.105s)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Integration with Async
|
|
43
|
+
|
|
44
|
+
The fiber profiler is optionally supported by `Async`. Simply enable the profiler using `FIBER_PROFILER_CAPTURE=true` to capture and report stalls.
|
|
45
|
+
|
|
46
|
+
## Default Environment Variables
|
|
47
|
+
|
|
48
|
+
### `FIBER_PROFILER_CAPTURE`
|
|
49
|
+
|
|
50
|
+
Set to `true` to enable capturing of stalled fibers.
|
|
51
|
+
|
|
52
|
+
### `FIBER_PROFILER_CAPTURE_STALL_THRESHOLD`
|
|
53
|
+
|
|
54
|
+
Set the threshold in seconds for reporting a stalled fiber. Default is `0.01`.
|
|
55
|
+
|
|
56
|
+
### `FIBER_PROFILER_CAPTURE_TRACK_CALLS`
|
|
57
|
+
|
|
58
|
+
Set to `true` to track calls within the fiber. Default is `true`. This can be disabled to reduce overhead.
|
|
59
|
+
|
|
60
|
+
### `FIBER_PROFILER_CAPTURE_SAMPLE_RATE`
|
|
61
|
+
|
|
62
|
+
Set the sample rate of the profiler as a percentage of all context switches. The default is 1.0 (100%).
|
|
63
|
+
|
|
64
|
+
## Analyzing Logs
|
|
65
|
+
|
|
66
|
+
If you collect your logs in a file (e.g. as `ndjson`) you can analyze them using the included `bake` commands:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
$ bundle exec bake input --file samples.ndjson fiber:profiler:analyze output
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
This will aggregate all the call logs and generate a short summary, ordered by duration.
|
data/context/index.yaml
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Automatically generated context index for Utopia::Project guides.
|
|
2
|
+
# Do not edit then files in this directory directly, instead edit the guides and then run `bake utopia:project:agent:context:update`.
|
|
3
|
+
---
|
|
4
|
+
description: A fiber stall profiler.
|
|
5
|
+
metadata:
|
|
6
|
+
documentation_uri: https://socketry.github.io/fiber-profiler/
|
|
7
|
+
source_code_uri: https://github.com/socketry/fiber-profiler.git
|
|
8
|
+
files:
|
|
9
|
+
- path: getting-started.md
|
|
10
|
+
title: Getting Started
|
|
11
|
+
description: This guide explains how to detect stalls using the fiber profiler.
|
|
@@ -181,8 +181,6 @@ static void Fiber_Profiler_Capture_compact(void *ptr) {
|
|
|
181
181
|
static void Fiber_Profiler_Capture_free(void *ptr) {
|
|
182
182
|
struct Fiber_Profiler_Capture *capture = (struct Fiber_Profiler_Capture*)ptr;
|
|
183
183
|
|
|
184
|
-
RUBY_ASSERT(capture->running == 0);
|
|
185
|
-
|
|
186
184
|
Fiber_Profiler_Stream_free(&capture->stream);
|
|
187
185
|
Fiber_Profiler_Deque_free(&capture->calls);
|
|
188
186
|
|
|
@@ -1,6 +1,44 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
|
-
# Copyright, 2025, by Samuel Williams.
|
|
4
|
+
# Copyright, 2025-2026, by Samuel Williams.
|
|
5
5
|
|
|
6
6
|
require_relative "native"
|
|
7
|
+
require_relative "fork_handler"
|
|
8
|
+
|
|
9
|
+
module Fiber::Profiler
|
|
10
|
+
# Thread-local storage for the active profiler capture.
|
|
11
|
+
::Thread.attr_accessor :fiber_profiler_capture
|
|
12
|
+
|
|
13
|
+
# Private module that wraps start/stop to manage thread-local storage.
|
|
14
|
+
module ThreadLocalCapture
|
|
15
|
+
# Start profiling and store the capture in the current thread's thread-local storage.
|
|
16
|
+
def start
|
|
17
|
+
result = super
|
|
18
|
+
|
|
19
|
+
if result
|
|
20
|
+
Thread.current.fiber_profiler_capture = self
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
return result
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Stop profiling and clear the capture from the current thread's thread-local storage.
|
|
27
|
+
def stop
|
|
28
|
+
result = super
|
|
29
|
+
|
|
30
|
+
if result
|
|
31
|
+
Thread.current.fiber_profiler_capture = nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
return result
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private_constant :ThreadLocalCapture
|
|
39
|
+
|
|
40
|
+
# Represents a running profiler capture.
|
|
41
|
+
class Capture
|
|
42
|
+
prepend ThreadLocalCapture
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2026, by Samuel Williams.
|
|
5
|
+
|
|
6
|
+
module Fiber::Profiler
|
|
7
|
+
# Private module that hooks into Process._fork to handle fork events.
|
|
8
|
+
#
|
|
9
|
+
# If `Scheduler#process_fork` hook is adopted in Ruby 4, this code can be removed after Ruby < 4 is no longer supported.
|
|
10
|
+
module ForkHandler
|
|
11
|
+
def _fork(&block)
|
|
12
|
+
result = super
|
|
13
|
+
|
|
14
|
+
if result.zero?
|
|
15
|
+
# Child process: disable the profiler for the current thread
|
|
16
|
+
if capture = Thread.current.fiber_profiler_capture
|
|
17
|
+
begin
|
|
18
|
+
capture.stop
|
|
19
|
+
rescue
|
|
20
|
+
# Ignore errors - the profiler may be in an invalid state after fork
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
return result
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private_constant :ForkHandler
|
|
30
|
+
|
|
31
|
+
# Hook into Process._fork to handle fork events automatically:
|
|
32
|
+
::Process.singleton_class.prepend(ForkHandler)
|
|
33
|
+
end
|
data/lib/fiber/profiler.rb
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
|
-
# Copyright, 2025, by Samuel Williams.
|
|
4
|
+
# Copyright, 2025-2026, by Samuel Williams.
|
|
5
5
|
|
|
6
6
|
require_relative "profiler/version"
|
|
7
7
|
require_relative "profiler/native"
|
|
8
|
+
require_relative "profiler/fork_handler"
|
|
8
9
|
|
|
9
10
|
module Fiber::Profiler
|
|
10
11
|
# The default profiler to use, if any.
|
data/license.md
CHANGED
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.6.0
|
|
22
|
+
|
|
23
|
+
- Fixed compatibility with `Process.fork`.
|
|
24
|
+
|
|
21
25
|
### v0.1.3
|
|
22
26
|
|
|
23
27
|
- Improved performance when not profiling (when sampling is enabled).
|
|
@@ -36,6 +40,22 @@ We welcome contributions to this project.
|
|
|
36
40
|
4. Push to the branch (`git push origin my-new-feature`).
|
|
37
41
|
5. Create new Pull Request.
|
|
38
42
|
|
|
43
|
+
### Running Tests
|
|
44
|
+
|
|
45
|
+
To run the test suite:
|
|
46
|
+
|
|
47
|
+
``` shell
|
|
48
|
+
bundle exec sus
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Making Releases
|
|
52
|
+
|
|
53
|
+
To make a new release:
|
|
54
|
+
|
|
55
|
+
``` shell
|
|
56
|
+
bundle exec bake gem:release:patch # or minor or major
|
|
57
|
+
```
|
|
58
|
+
|
|
39
59
|
### Developer Certificate of Origin
|
|
40
60
|
|
|
41
61
|
In order to protect users of this project, we require all contributors to comply with the [Developer Certificate of Origin](https://developercertificate.org/). This ensures that all contributions are properly licensed and attributed.
|
data/releases.md
CHANGED
data.tar.gz.sig
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
j��(��6���x��PU�@��� ǒ����t��h���1��x�e��:��Eaʩ̵�����at4�7�iB߆�ɬ�c���1��QsĹ��Y'ߘYg�r7=�-����0�z�ݐBL��#~��m�X�?����55�l�M�ڂE$��<(f���kX�H��`6ї(}��0��Q&<2_J�qV��3h���){���7�� �G�
|
|
2
|
+
�
|
|
3
|
+
o��
|
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.
|
|
4
|
+
version: 0.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Samuel Williams
|
|
@@ -43,6 +43,9 @@ extensions:
|
|
|
43
43
|
- ext/extconf.rb
|
|
44
44
|
extra_rdoc_files: []
|
|
45
45
|
files:
|
|
46
|
+
- bake/fiber/profiler/analyze.rb
|
|
47
|
+
- context/getting-started.md
|
|
48
|
+
- context/index.yaml
|
|
46
49
|
- ext/extconf.rb
|
|
47
50
|
- ext/fiber/profiler/capture.c
|
|
48
51
|
- ext/fiber/profiler/capture.h
|
|
@@ -55,6 +58,7 @@ files:
|
|
|
55
58
|
- ext/fiber/profiler/time.h
|
|
56
59
|
- lib/fiber/profiler.rb
|
|
57
60
|
- lib/fiber/profiler/capture.rb
|
|
61
|
+
- lib/fiber/profiler/fork_handler.rb
|
|
58
62
|
- lib/fiber/profiler/native.rb
|
|
59
63
|
- lib/fiber/profiler/version.rb
|
|
60
64
|
- license.md
|
|
@@ -73,14 +77,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
73
77
|
requirements:
|
|
74
78
|
- - ">="
|
|
75
79
|
- !ruby/object:Gem::Version
|
|
76
|
-
version: '3.
|
|
80
|
+
version: '3.3'
|
|
77
81
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
82
|
requirements:
|
|
79
83
|
- - ">="
|
|
80
84
|
- !ruby/object:Gem::Version
|
|
81
85
|
version: '0'
|
|
82
86
|
requirements: []
|
|
83
|
-
rubygems_version:
|
|
87
|
+
rubygems_version: 4.0.6
|
|
84
88
|
specification_version: 4
|
|
85
89
|
summary: A fiber stall profiler.
|
|
86
90
|
test_files: []
|
metadata.gz.sig
CHANGED
|
Binary file
|