Project

General

Profile

Actions

Feature #18411

closed

Introduce `Fiber.blocking` for disabling scheduler.

Added by ioquatix (Samuel Williams) almost 3 years ago. Updated about 2 years ago.

Status:
Closed
Target version:
-
[ruby-core:106707]

Description

When implementing pure-ruby IO scheduler, we may need to invoke some Ruby IO operations without entering the scheduler.

def io_write(fiber, io, buffer, length)
  offset = 0
  
  while length > 0
    # From offset until the end:
    chunk = buffer.to_str(offset, length)
    case result = io.write_nonblock(chunk, exception: false)
    when :wait_readable
      self.io_wait(fiber, io, IO::READABLE)
    when :wait_writable
      self.io_wait(fiber, io, IO::WRITABLE)
    else
      offset += result
      length -= result
    end
  end
  
  return offset
end

There are some cases where even in this code read_nonblock can invoke fiber scheduler creating infinite recursion.

Therefore, I propose to introduce Fiber.blocking{...} which has almost identical implementation to Fiber.new(blocking: true) {}.resume.

In the above code, we change the line:

    case result = io.write_nonblock(chunk, exception: false)

to

    case result = Fiber.blocking{io.write_nonblock(chunk, exception: false)}

This ensures that write_nonblock can never enter the scheduler again.

Updated by ioquatix (Samuel Williams) almost 3 years ago

@matz (Yukihiro Matsumoto) this isn't strictly necessary but makes pure Ruby implementation of IO read/write hooks more efficient. I'm not sure if there is valid case for general user code. Can we consider it for Ruby 3.1?

Actions #2

Updated by ioquatix (Samuel Williams) almost 3 years ago

  • Description updated (diff)
Actions #3

Updated by jeremyevans0 (Jeremy Evans) almost 3 years ago

  • Tracker changed from Bug to Feature
  • Backport deleted (2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN)

Updated by ko1 (Koichi Sasada) about 2 years ago

Let me confirm that why write_nonblock calls a fiber scheduler?
Or does it solve if write_nonblock doesn't call a fiber scheduler?

Updated by ioquatix (Samuel Williams) about 2 years ago

io_uring handles non-blocking read and write system calls using the ring buffer. So even read_nonblock and write_nonblock system calls can go via the fiber scheduler. The system call itself is asynchronous even if the IO is non-blocking. I have not investigated the performance much since io_uring has not been in a completely usable state yet. But recently it was much better, so I may begin this evaluation soon.

Updated by ioquatix (Samuel Williams) about 2 years ago

  • Status changed from Open to Closed
  • Assignee set to ioquatix (Samuel Williams)

It was merged.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0