[#100309] How to use backport custom field — Jun Aruga <jaruga@...>
Please allow my ignorance.
9 messages
2020/10/06
[#100310] Re: How to use backport custom field
— "NARUSE, Yui" <naruse@...>
2020/10/06
IkJhY2twb3J0IGN1c3RvbSBmaWVsZCIgaXMgb25seSBhdmFpbGFibGUgZm9yIHRpY2tldHMgd2hv
[#100311] Re: How to use backport custom field
— Jun Aruga <jaruga@...>
2020/10/06
On Tue, Oct 6, 2020 at 4:44 PM NARUSE, Yui <[email protected]> wrote:
[#100314] Re: How to use backport custom field
— "NARUSE, Yui" <naruse@...>
2020/10/06
VGhhbmsgeW91IGZvciBjb25maXJtYXRpb24uCkkgY2hlY2tlZCBhZ2FpbiBhbmQgdG8gZWRpdCBi
[#100322] Re: How to use backport custom field
— Jun Aruga <jaruga@...>
2020/10/07
On Tue, Oct 6, 2020 at 7:25 PM NARUSE, Yui <[email protected]> wrote:
[#100326] Re: How to use backport custom field
— "NARUSE, Yui" <naruse@...>
2020/10/07
SSBhZGRlZCB5b3UgdG8gIlJlcG9ydGVyIiByb2xlIGluIHRoZSBwcm9qZWN0CgoyMDIw5bm0MTDm
[#100327] Re: How to use backport custom field
— Jun Aruga <jaruga@...>
2020/10/07
On Wed, Oct 7, 2020 at 1:42 PM NARUSE, Yui <[email protected]> wrote:
[ruby-core:100677] [Ruby master Feature#17298] Ractor's basket communication APIs
From:
eregontp@...
Date:
2020-10-31 10:47:53 UTC
List:
ruby-core #100677
Issue #17298 has been updated by Eregon (Benoit Daloze).
For the first example, isn't `move: true` much simpler?
```ruby
bridge = Ractor.new do
Ractor.yield Ractor.receive, move: true
end
consumer = Ractor.new bridge do |from|
obj = from.take
do_task(obj)
end
msg = [1, 2, 3]
bridge.send msg
```
Having `move: true` on `Ractor.yield` means we need to wait to know which Ractor to move the object to, but that seems fine and transparent to the user.
The bridge Ractor can ensure it will no longer refer to the message, so it's perfectly safe to move there.
Similar for the other 3 examples in the benchmark.
Adding 4 new methods for this seem heavy to me. Also, exposing the serialized representation seems bad.
For instance, there might an efficient deep_copy/dup/clone in the future, and then there is no reason to use Marshal anymore, and no serialized representation.
Explicitly deeply freezing the message (e.g., with Ractor.make_shareable, or some kwarg to freeze on send/yield) seems a good way too, and easier to reason about.
Sending a copy of a mutable object seems useless to me, because mutations will not affect the sender, it only mutates a copy.
So either freezing or moving seems more useful, and both avoid copying.
----------------------------------------
Feature #17298: Ractor's basket communication APIs
https://bugs.ruby-lang.org/issues/17298#change-88319
* Author: ko1 (Koichi Sasada)
* Status: Open
* Priority: Normal
----------------------------------------
This ticket proposes send_basket/send_receive, yield_basket/take_basket APIs to make effective and flexible bridge ractors.
## Background
When we want to send an object as a message, usually we need to copy it.
Copying is achieved by marshal protocol, and receiver load it immediately.
If we want to make a bridge ractor which receive a message and send it to another ractor, the immediate loading is not effective.
```ruby
bridge = Ractor.new do
Ractor.yield Ractor.receive
end
consumer = Ractor.new bridge do |from|
obj = from.take
do_task(obj)
end
msg = [1, 2, 3]
bridge.send msg
```
In this case, the array (`[1, 2, 3]`) is
* (1) dumped at the first `bridge.send msg`
* (2) loaded at `Ractor.receive`
* (3) dumped again at `Ractor.yield`
* (4) laoded at `from.take`
Essentially we only need one dump/load pair, but now it needs 2 pairs.
Mixing "moving" is more complex.
Now there is no way to pass the "moving" status to the bridge ractors, we can not make a moving bridge.
## Proposal
To make more effective and flexible bridge ractors, we propose new basket APIs
* `Ractor.receive_basket`
* `Ractor#send_basket`
* `Ractor.take_basket`
* `Ractor.yield_basket`
They receive a message, but remaining dumped state and send it without dumping again.
We can rewrite the above example with these APIs.
```ruby
bridge = Ractor.new do
Ractor.yield_basket Ractor.receive_basket
end
consumer = Ractor.new bridge do |from|
obj = from.take
do_task(obj)
end
msg = [1, 2, 3]
bridge.send msg
```
In this case,
* (1) dumped at the first `bridge.send msg`
* (2) laoded at `from.take`
we only need one dump/load pair.
## Implementation
https://github.com/ruby/ruby/pull/3725
## Evaluation
The following program makes 4 type of bridges and pass an array as a message through them.
```ruby
USE_BASKET = false
receive2yield = Ractor.new do
loop do
if USE_BASKET
Ractor.yield_basket Ractor.receive_basket
else
Ractor.yield Ractor.receive
end
end
end
receive2send = Ractor.new receive2yield do |r|
loop do
if USE_BASKET
r.send_basket Ractor.receive_basket
else
r.send Ractor.receive
end
end
end
take2yield = Ractor.new receive2yield do |from|
loop do
if USE_BASKET
Ractor.yield_basket from.take_basket
else
Ractor.yield from.take
end
end
end
take2send = Ractor.new take2yield, Ractor.current do |from, to|
loop do
if USE_BASKET
to.send_basket from.take_basket
else
to.send from.take
end
end
end
AN = 1_000
LN = 10_000
ary = Array.new(AN) # 1000
LN.times{
receive2send << ary
Ractor.receive
}
# This program passes the message as:
# main ->
# receive2send ->
# receive2yield ->
# take2yield ->
# take2send ->
# main
```
The result is:
```
w/ basket API 0m2.056s
w/o basket API 0m5.974s
```
on my machine (=~ x3 faster).
(BTW, if we have a TVar, we can change the value `USE_BASKET` dynamically)
## Discussion
### naming
Of course, naming is an issue. Now, I named "_basket" because source code using this terminology.
There are other candidates:
* container metaphor
* package
* parcel
* box
* envelope
* packet (maybe bad idea because of confusion of networking)
* bundle (maybe bad idea because of confusion of bin/bundle)
* "don't touch the content" metaphor
* raw
* sealed
* unopened
I like "basket" because I like picnic.
### feature
Now, basket is represented by "Ractor::Basket" and there is no methods.
We can add the following feature:
* `Ractor::Basket#sender` return the sending ractor.
* `Ractor::Basket#sender = a_ractor` change the sending ractor.
* `Ractor::Basket#value` returns the content.
There was another proposal `Ractor.recvfrom`, but we only need these APIs.
--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:[email protected]?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>