ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:116827] [Ruby master Feature#20276] Introduce Fiber interfaces for Ractors
@ 2024-02-17 20:55 forthoney (Seong-Heon Jung) via ruby-core
  2024-02-19  1:40 ` [ruby-core:116836] [Ruby master Feature#20276] Introduce Fiber interfaces for Blocking operations on Ractors ko1 (Koichi Sasada) via ruby-core
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: forthoney (Seong-Heon Jung) via ruby-core @ 2024-02-17 20:55 UTC (permalink / raw
  To: ruby-core; +Cc: forthoney (Seong-Heon Jung)

Issue #20276 has been reported by forthoney (Seong-Heon Jung).

----------------------------------------
Feature #20276: Introduce Fiber interfaces for Ractors
https://bugs.ruby-lang.org/issues/20276

* Author: forthoney (Seong-Heon Jung)
* Status: Open
* Priority: Normal
----------------------------------------
## Motivation
I am trying to build a web server with Ractors. The lifecycle for a request in the current implementation is 
1. main ractor buffers request
2. main ractor sends request to worker ractor
3. worker ractor sends response to main ractor
4. main ractor writes response
5. repeat

The main ractor utilizes the Async gem (specifically async-http) to handle connections concurrently, meaning each request is handled on a separate fiber.
The issue I am running into is after I send a request to a worker ractor, I need to do a blocking wait until I receive a response.
While I am waiting for the response, I cannot take any more connections.

## Solution
If the fiber scheduler had a hook for `Ractor.receive` or `Ractor#take` (both of which are blocking), the main ractor can send the message, handle other connections while the worker processes the request. When the worker produces a message, it will then take the reqeust and write it in the socket.




-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [ruby-core:116836] [Ruby master Feature#20276] Introduce Fiber interfaces for Blocking operations on Ractors
  2024-02-17 20:55 [ruby-core:116827] [Ruby master Feature#20276] Introduce Fiber interfaces for Ractors forthoney (Seong-Heon Jung) via ruby-core
@ 2024-02-19  1:40 ` ko1 (Koichi Sasada) via ruby-core
  2024-02-19 18:20 ` [ruby-core:116850] " forthoney (Seong-Heon Jung) via ruby-core
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: ko1 (Koichi Sasada) via ruby-core @ 2024-02-19  1:40 UTC (permalink / raw
  To: ruby-core; +Cc: ko1 (Koichi Sasada)

Issue #20276 has been updated by ko1 (Koichi Sasada).

Status changed from Open to Feedback

I understand the motivation but now the ractor-thread combination is not well-defined yet and combination with Fiber (scheduler) is also earlier (because of specification and implementation).


----------------------------------------
Feature #20276: Introduce Fiber interfaces for Blocking operations on Ractors
https://bugs.ruby-lang.org/issues/20276#change-106861

* Author: forthoney (Seong-Heon Jung)
* Status: Feedback
* Priority: Normal
----------------------------------------
### Motivation
I am trying to build a web server with Ractors. The lifecycle for a request in the current implementation is 

1. main ractor sends request to worker ractor
2. worker ractor handles response
3. worker ractor sends response to main ractor
4. main ractor writes response
5. repeat

The main ractor utilizes the Async gem (specifically async-http) to handle connections concurrently, meaning each request is handled on a separate fiber.
The issue I am running into is after I send a request to a worker ractor, I need to do a blocking wait until I receive a response.
While I am waiting for the response, I cannot take any more connections.


### Solution
If the fiber scheduler had a hook for `Ractor.receive` or `Ractor#take` (both of which are blocking), the main ractor can send the message, handle other connections while the worker processes the request. When the worker produces a message, it will then take the reqeust and write it in the socket. Specifically, I think the `block` and `unblock` hooks should be implemented for Ractors, considering Threads and Mutexes already use them.




-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [ruby-core:116850] [Ruby master Feature#20276] Introduce Fiber interfaces for Blocking operations on Ractors
  2024-02-17 20:55 [ruby-core:116827] [Ruby master Feature#20276] Introduce Fiber interfaces for Ractors forthoney (Seong-Heon Jung) via ruby-core
  2024-02-19  1:40 ` [ruby-core:116836] [Ruby master Feature#20276] Introduce Fiber interfaces for Blocking operations on Ractors ko1 (Koichi Sasada) via ruby-core
@ 2024-02-19 18:20 ` forthoney (Seong-Heon Jung) via ruby-core
  2024-03-11 23:06 ` [ruby-core:117102] " ioquatix (Samuel Williams) via ruby-core
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: forthoney (Seong-Heon Jung) via ruby-core @ 2024-02-19 18:20 UTC (permalink / raw
  To: ruby-core; +Cc: forthoney (Seong-Heon Jung)

Issue #20276 has been updated by forthoney (Seong-Heon Jung).


ko1 (Koichi Sasada) wrote in #note-2:
> I understand the motivation but now the ractor-thread combination is not well-defined yet and combination with Fiber (scheduler) is also earlier (because of Ractor's specification and implementation).

I actually tried writing out some code to picture how this might be implemented, and I understand the complexity now. In the current implementation `rb_fiber_scheduler_block/unblock`, if `ractor_a` were to call `ractor_b.take` we would need the following process:
1. `ractor_a` emits `block` event to `ractor_a`'s scheduler
2. `ractor_a`'s current fiber yields, and different fiber runs on `ractor_a`
3. `ractor_b` calls yield
4. `ractor_b` emits `unblock` event to **`ractor_a`**'s scheduler

With the strict object sharing rules between ractors, I can see why it may require a major rewrite to make Ractor blocking operations a fiber-scheduler event.

How is this alternative?
Instead of relying on automatic scheduling via Fiber scheduler events, we can rely a bit on programmer intervention.
If there is a method like `Ractor#take_nonblock` which works similar to `IO#read_nonblock`, the programmer can write code like
```ruby
loop do
  msg = other_ractor.take_nonblock
rescue Errno::EAGAIN
  task.yield
  retry
end
```
This may not be 100% efficient since the scheduler would need to continuously "ask", but better than this not being possible at all.


----------------------------------------
Feature #20276: Introduce Fiber interfaces for Blocking operations on Ractors
https://bugs.ruby-lang.org/issues/20276#change-106881

* Author: forthoney (Seong-Heon Jung)
* Status: Feedback
* Priority: Normal
----------------------------------------
### Motivation
I am trying to build a web server with Ractors. The lifecycle for a request in the current implementation is 

1. main ractor sends request to worker ractor
2. worker ractor handles response
3. worker ractor sends response to main ractor
4. main ractor writes response
5. repeat

The main ractor utilizes the Async gem (specifically async-http) to handle connections concurrently, meaning each request is handled on a separate fiber.
The issue I am running into is after I send a request to a worker ractor, I need to do a blocking wait until I receive a response.
While I am waiting for the response, I cannot take any more connections.


### Solution
If the fiber scheduler had a hook for `Ractor.receive` or `Ractor#take` (both of which are blocking), the main ractor can send the message, handle other connections while the worker processes the request. When the worker produces a message, it will then take the reqeust and write it in the socket. Specifically, I think the `block` and `unblock` hooks should be implemented for Ractors, considering Threads and Mutexes already use them.




-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [ruby-core:117102] [Ruby master Feature#20276] Introduce Fiber interfaces for Blocking operations on Ractors
  2024-02-17 20:55 [ruby-core:116827] [Ruby master Feature#20276] Introduce Fiber interfaces for Ractors forthoney (Seong-Heon Jung) via ruby-core
  2024-02-19  1:40 ` [ruby-core:116836] [Ruby master Feature#20276] Introduce Fiber interfaces for Blocking operations on Ractors ko1 (Koichi Sasada) via ruby-core
  2024-02-19 18:20 ` [ruby-core:116850] " forthoney (Seong-Heon Jung) via ruby-core
@ 2024-03-11 23:06 ` ioquatix (Samuel Williams) via ruby-core
  2024-03-12  4:58 ` [ruby-core:117108] " forthoney (Seong-Heon Jung) via ruby-core
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: ioquatix (Samuel Williams) via ruby-core @ 2024-03-11 23:06 UTC (permalink / raw
  To: ruby-core; +Cc: ioquatix (Samuel Williams)

Issue #20276 has been updated by ioquatix (Samuel Williams).


I support this proposal.

A simple way to deal with this right now might be the following code (I have not tested it):

```ruby
Thread.new do
  other_ractor.take
end.value
```

In general, the `block`/`unblock` operations should be sufficient, but it might require the ability for `Ractor` to invoke functionality across it's boundary OR we might need to implement some RPC mechanism (this is common in Actor based concurrency). 

----------------------------------------
Feature #20276: Introduce Fiber interfaces for Blocking operations on Ractors
https://bugs.ruby-lang.org/issues/20276#change-107175

* Author: forthoney (Seong-Heon Jung)
* Status: Feedback
----------------------------------------
### Motivation
I am trying to build a web server with Ractors. The lifecycle for a request in the current implementation is 

1. main ractor sends request to worker ractor
2. worker ractor handles response
3. worker ractor sends response to main ractor
4. main ractor writes response
5. repeat

The main ractor utilizes the Async gem (specifically async-http) to handle connections concurrently, meaning each request is handled on a separate fiber.
The issue I am running into is after I send a request to a worker ractor, I need to do a blocking wait until I receive a response.
While I am waiting for the response, I cannot take any more connections.


### Solution
If the fiber scheduler had a hook for `Ractor.receive` or `Ractor#take` (both of which are blocking), the main ractor can send the message, handle other connections while the worker processes the request. When the worker produces a message, it will then take the reqeust and write it in the socket. Specifically, I think the `block` and `unblock` hooks should be implemented for Ractors, considering Threads and Mutexes already use them.




-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [ruby-core:117108] [Ruby master Feature#20276] Introduce Fiber interfaces for Blocking operations on Ractors
  2024-02-17 20:55 [ruby-core:116827] [Ruby master Feature#20276] Introduce Fiber interfaces for Ractors forthoney (Seong-Heon Jung) via ruby-core
                   ` (2 preceding siblings ...)
  2024-03-11 23:06 ` [ruby-core:117102] " ioquatix (Samuel Williams) via ruby-core
@ 2024-03-12  4:58 ` forthoney (Seong-Heon Jung) via ruby-core
  2024-03-12  5:00 ` [ruby-core:117109] " forthoney (Seong-Heon Jung) via ruby-core
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: forthoney (Seong-Heon Jung) via ruby-core @ 2024-03-12  4:58 UTC (permalink / raw
  To: ruby-core; +Cc: forthoney (Seong-Heon Jung)

Issue #20276 has been updated by forthoney (Seong-Heon Jung).


ioquatix (Samuel Williams) wrote in #note-4:
> I support this proposal.
> 
> A simple way to deal with this right now might be the following code (I have not tested it):
> 
> ```ruby
> Thread.new do
>   other_ractor.take
> end.value
> ```
> 
> In general, the `block`/`unblock` operations should be sufficient, but it might require the ability for `Ractor` to invoke functionality across it's boundary OR we might need to implement some RPC mechanism (this is common in Actor based concurrency).

Tested on locally and it seems to work, at least with Async. Here's my code.
```ruby
Async do |task|
  1.upto(3) do
    r = Ractor.new do
      Ractor.recv
      fib = ->(x) { x < 2 ? 1 : fib.call(x - 2) + fib.call(x - 1) }
      puts "fin"
    end
    task.async do 
      Thread.new do
        r.send(nil) # ractor start
        r.take
      end.value
    end
  end
end
```
Not very scientific but the results are printed at roughly the same time.

----------------------------------------
Feature #20276: Introduce Fiber interfaces for Blocking operations on Ractors
https://bugs.ruby-lang.org/issues/20276#change-107183

* Author: forthoney (Seong-Heon Jung)
* Status: Feedback
----------------------------------------
### Motivation
I am trying to build a web server with Ractors. The lifecycle for a request in the current implementation is 

1. main ractor sends request to worker ractor
2. worker ractor handles response
3. worker ractor sends response to main ractor
4. main ractor writes response
5. repeat

The main ractor utilizes the Async gem (specifically async-http) to handle connections concurrently, meaning each request is handled on a separate fiber.
The issue I am running into is after I send a request to a worker ractor, I need to do a blocking wait until I receive a response.
While I am waiting for the response, I cannot take any more connections.


### Solution
If the fiber scheduler had a hook for `Ractor.receive` or `Ractor#take` (both of which are blocking), the main ractor can send the message, handle other connections while the worker processes the request. When the worker produces a message, it will then take the reqeust and write it in the socket. Specifically, I think the `block` and `unblock` hooks should be implemented for Ractors, considering Threads and Mutexes already use them.




-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [ruby-core:117109] [Ruby master Feature#20276] Introduce Fiber interfaces for Blocking operations on Ractors
  2024-02-17 20:55 [ruby-core:116827] [Ruby master Feature#20276] Introduce Fiber interfaces for Ractors forthoney (Seong-Heon Jung) via ruby-core
                   ` (3 preceding siblings ...)
  2024-03-12  4:58 ` [ruby-core:117108] " forthoney (Seong-Heon Jung) via ruby-core
@ 2024-03-12  5:00 ` forthoney (Seong-Heon Jung) via ruby-core
  2024-03-12 21:25 ` [ruby-core:117123] " ioquatix (Samuel Williams) via ruby-core
  2024-03-18 19:09 ` [ruby-core:117217] " forthoney (Seong-Heon Jung) via ruby-core
  6 siblings, 0 replies; 8+ messages in thread
From: forthoney (Seong-Heon Jung) via ruby-core @ 2024-03-12  5:00 UTC (permalink / raw
  To: ruby-core; +Cc: forthoney (Seong-Heon Jung)

Issue #20276 has been updated by forthoney (Seong-Heon Jung).


On a side note, I may have unintentionally discovered an IRB bug in the process. If you run the above in IRB and use Ctrl-C to exit, IRB hangs and becomes unresponsive.

----------------------------------------
Feature #20276: Introduce Fiber interfaces for Blocking operations on Ractors
https://bugs.ruby-lang.org/issues/20276#change-107184

* Author: forthoney (Seong-Heon Jung)
* Status: Feedback
----------------------------------------
### Motivation
I am trying to build a web server with Ractors. The lifecycle for a request in the current implementation is 

1. main ractor sends request to worker ractor
2. worker ractor handles response
3. worker ractor sends response to main ractor
4. main ractor writes response
5. repeat

The main ractor utilizes the Async gem (specifically async-http) to handle connections concurrently, meaning each request is handled on a separate fiber.
The issue I am running into is after I send a request to a worker ractor, I need to do a blocking wait until I receive a response.
While I am waiting for the response, I cannot take any more connections.


### Solution
If the fiber scheduler had a hook for `Ractor.receive` or `Ractor#take` (both of which are blocking), the main ractor can send the message, handle other connections while the worker processes the request. When the worker produces a message, it will then take the reqeust and write it in the socket. Specifically, I think the `block` and `unblock` hooks should be implemented for Ractors, considering Threads and Mutexes already use them.




-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [ruby-core:117123] [Ruby master Feature#20276] Introduce Fiber interfaces for Blocking operations on Ractors
  2024-02-17 20:55 [ruby-core:116827] [Ruby master Feature#20276] Introduce Fiber interfaces for Ractors forthoney (Seong-Heon Jung) via ruby-core
                   ` (4 preceding siblings ...)
  2024-03-12  5:00 ` [ruby-core:117109] " forthoney (Seong-Heon Jung) via ruby-core
@ 2024-03-12 21:25 ` ioquatix (Samuel Williams) via ruby-core
  2024-03-18 19:09 ` [ruby-core:117217] " forthoney (Seong-Heon Jung) via ruby-core
  6 siblings, 0 replies; 8+ messages in thread
From: ioquatix (Samuel Williams) via ruby-core @ 2024-03-12 21:25 UTC (permalink / raw
  To: ruby-core; +Cc: ioquatix (Samuel Williams)

Issue #20276 has been updated by ioquatix (Samuel Williams).


If I had to take a guess, I'd say it's a bug with waiting on a Ractor while handling signals?

----------------------------------------
Feature #20276: Introduce Fiber interfaces for Blocking operations on Ractors
https://bugs.ruby-lang.org/issues/20276#change-107198

* Author: forthoney (Seong-Heon Jung)
* Status: Feedback
----------------------------------------
### Motivation
I am trying to build a web server with Ractors. The lifecycle for a request in the current implementation is 

1. main ractor sends request to worker ractor
2. worker ractor handles response
3. worker ractor sends response to main ractor
4. main ractor writes response
5. repeat

The main ractor utilizes the Async gem (specifically async-http) to handle connections concurrently, meaning each request is handled on a separate fiber.
The issue I am running into is after I send a request to a worker ractor, I need to do a blocking wait until I receive a response.
While I am waiting for the response, I cannot take any more connections.


### Solution
If the fiber scheduler had a hook for `Ractor.receive` or `Ractor#take` (both of which are blocking), the main ractor can send the message, handle other connections while the worker processes the request. When the worker produces a message, it will then take the reqeust and write it in the socket. Specifically, I think the `block` and `unblock` hooks should be implemented for Ractors, considering Threads and Mutexes already use them.




-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [ruby-core:117217] [Ruby master Feature#20276] Introduce Fiber interfaces for Blocking operations on Ractors
  2024-02-17 20:55 [ruby-core:116827] [Ruby master Feature#20276] Introduce Fiber interfaces for Ractors forthoney (Seong-Heon Jung) via ruby-core
                   ` (5 preceding siblings ...)
  2024-03-12 21:25 ` [ruby-core:117123] " ioquatix (Samuel Williams) via ruby-core
@ 2024-03-18 19:09 ` forthoney (Seong-Heon Jung) via ruby-core
  6 siblings, 0 replies; 8+ messages in thread
From: forthoney (Seong-Heon Jung) via ruby-core @ 2024-03-18 19:09 UTC (permalink / raw
  To: ruby-core; +Cc: forthoney (Seong-Heon Jung)

Issue #20276 has been updated by forthoney (Seong-Heon Jung).


ioquatix (Samuel Williams) wrote in #note-7:
> If I had to take a guess, I'd say it's a bug with waiting on a Ractor while handling signals?

Under closer inspection, the `Thread#join` workaround should work in theory but actually deadlocks in practice, likely due to an implementation bug. [Here](https://bugs.ruby-lang.org/issues/20346)'s the relevant bug report. IRB is likely unresponsive because of this deadlock.

----------------------------------------
Feature #20276: Introduce Fiber interfaces for Blocking operations on Ractors
https://bugs.ruby-lang.org/issues/20276#change-107303

* Author: forthoney (Seong-Heon Jung)
* Status: Feedback
----------------------------------------
### Motivation
I am trying to build a web server with Ractors. The lifecycle for a request in the current implementation is 

1. main ractor sends request to worker ractor
2. worker ractor handles response
3. worker ractor sends response to main ractor
4. main ractor writes response
5. repeat

The main ractor utilizes the Async gem (specifically async-http) to handle connections concurrently, meaning each request is handled on a separate fiber.
The issue I am running into is after I send a request to a worker ractor, I need to do a blocking wait until I receive a response.
While I am waiting for the response, I cannot take any more connections.


### Solution
If the fiber scheduler had a hook for `Ractor.receive` or `Ractor#take` (both of which are blocking), the main ractor can send the message, handle other connections while the worker processes the request. When the worker produces a message, it will then take the reqeust and write it in the socket. Specifically, I think the `block` and `unblock` hooks should be implemented for Ractors, considering Threads and Mutexes already use them.




-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2024-03-18 19:09 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-02-17 20:55 [ruby-core:116827] [Ruby master Feature#20276] Introduce Fiber interfaces for Ractors forthoney (Seong-Heon Jung) via ruby-core
2024-02-19  1:40 ` [ruby-core:116836] [Ruby master Feature#20276] Introduce Fiber interfaces for Blocking operations on Ractors ko1 (Koichi Sasada) via ruby-core
2024-02-19 18:20 ` [ruby-core:116850] " forthoney (Seong-Heon Jung) via ruby-core
2024-03-11 23:06 ` [ruby-core:117102] " ioquatix (Samuel Williams) via ruby-core
2024-03-12  4:58 ` [ruby-core:117108] " forthoney (Seong-Heon Jung) via ruby-core
2024-03-12  5:00 ` [ruby-core:117109] " forthoney (Seong-Heon Jung) via ruby-core
2024-03-12 21:25 ` [ruby-core:117123] " ioquatix (Samuel Williams) via ruby-core
2024-03-18 19:09 ` [ruby-core:117217] " forthoney (Seong-Heon Jung) via ruby-core

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).