Skip to content

Add support for IO::Event::Profiler. #375

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion async.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Gem::Specification.new do |spec|

spec.add_dependency "console", "~> 1.29"
spec.add_dependency "fiber-annotation"
spec.add_dependency "io-event", "~> 1.7"
spec.add_dependency "io-event", "~> 1.9"
spec.add_dependency "traces", "~> 0.15"
spec.add_dependency "metrics", "~> 0.12"
end
1 change: 1 addition & 0 deletions gems.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
gemspec

# gem "io-event", git: "https://github.com/socketry/io-event.git"
gem "fiber-profiler"

group :maintenance, optional: true do
gem "bake-gem"
Expand Down
30 changes: 23 additions & 7 deletions lib/async/scheduler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@
require "resolv"

module Async
begin
require "fiber/profiler"
Profiler = Fiber::Profiler
rescue LoadError
# Fiber::Profiler is not available.
Profiler = nil
end

# Handles scheduling of fibers. Implements the fiber scheduler interface.
class Scheduler < Node
DEFAULT_WORKER_POOL = ENV.fetch("ASYNC_SCHEDULER_DEFAULT_WORKER_POOL", nil).then do |value|
Expand Down Expand Up @@ -42,10 +50,12 @@ def self.supported?
# @public Since *Async v1*.
# @parameter parent [Node | Nil] The parent node to use for task hierarchy.
# @parameter selector [IO::Event::Selector] The selector to use for event handling.
def initialize(parent = nil, selector: nil, worker_pool: DEFAULT_WORKER_POOL)
def initialize(parent = nil, selector: nil, profiler: Profiler&.default, worker_pool: DEFAULT_WORKER_POOL)
super(parent)

@selector = selector || ::IO::Event::Selector.new(Fiber.current)
@profiler = profiler

@interrupted = false

@blocked = 0
Expand Down Expand Up @@ -492,13 +502,19 @@ def stop
def run(...)
Kernel.raise ClosedError if @selector.nil?

initial_task = self.async(...) if block_given?

self.run_loop do
run_once
begin
@profiler&.start

initial_task = self.async(...) if block_given?

self.run_loop do
run_once
end

return initial_task
ensure
@profiler&.stop
end

return initial_task
end

# Start an asynchronous task within the specified reactor. The task will be executed until the first blocking call, at which point it will yield and and this method will return.
Expand Down
4 changes: 3 additions & 1 deletion test/io.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,14 @@
it "can write with timeout" do
skip_unless_constant_defined(:TimeoutError, IO)

big = "x" * 1024 * 1024

input, output = IO.pipe
output.timeout = 0.001

expect do
while true
output.write("Hello")
output.write(big)
end
end.to raise_exception(::IO::TimeoutError)
end
Expand Down
Loading