Issue #21869 has been updated by ko1 (Koichi Sasada). synacker (Mikhail Milovidov) wrote in #note-4:
Yes, it blocks if the queue empty. The method ```receive_all``` accepts a limit parameter: 1. ```limit > 0```: collects up to ```limit``` messages (may return fewer if fewer are queued). Blocks if the queue is empty. 2. ```limit == 0```: returns an empty array immediately (no blocking) 3. ```limit < 0``` or ```nil``` (default): returns all messages from the queue or blocks if the queue is empty
The parameter `limit` is not in the description. Let me clarify `limit == 0`. In above quote, it returns empty array. If it returns `[]` always, I think we don't need to introduce it. If it returns existing messages, we can consider about it. For this purpose, it is possible to introduce another parameter such as `timeout: 0`. - `receive_all(3, timeout: 0)` returns up to 3 messages already arrived. If there is no messages arrived, returns `nil` (timeout). - `receive_all(timeout: 1)` returns all messages in a queue, or wait for 1 second. If a message arrived, return the `[received_one_message]`. If no message arrived in 1 second, return `nil`. - `receive_all(0 or negative parameter)` raises an exception. We can extend `timeout:` on `receive` method with same manner. ---------------------------------------- Feature #21869: Add receive_all Method to Ractor API for Message Batching https://bugs.ruby-lang.org/issues/21869#change-116724 * Author: synacker (Mikhail Milovidov) * Status: Open * Assignee: ractor ---------------------------------------- **Summary** The Ractor API provides an excellent mechanism for inter‑thread communication, but it currently lacks a built‑in message batching technique. I propose adding a receive_all method to enable batch processing of messages, which can significantly improve performance in high‑load scenarios. **Motivation** In distributed queued systems, processing messages one‑by‑one (as with the current receive method) can introduce unnecessary overhead. Batch processing allows: Reduced context‑switching overhead. More efficient I/O operations (e.g., fewer file writes). Better throughput in high‑concurrency environments. **Proposed Solution** Add a receive_all method to the Ractor API that: Returns all available messages in the Ractor’s mailbox at once (as an array). **Demonstration Code** Below is a benchmark comparing individual receive vs. batch receive_all: ``` ruby require 'benchmark' class RactorsTest def initialize(count) @count = count @ractor1 = Ractor.new(count, 'output1.txt') do |count, filename| File.open(filename, 'w') do |file| while count.positive? message = receive file.write("Ractor 1 received message: #{message}\n") file.flush count -= 1 end end end @ractor2 = Ractor.new(count, 'output2.txt') do |count, filename| File.open(filename, 'w') do |file| while count.positive? messages = receive_all messages.each do |message| file.write("Ractor 2 received message: #{message}\n") end count -= messages.length file.flush end end end end def run1 @count.times do |i| @ractor1.send("Message #{i + 1}") end @ractor1.join end def run2 @count.times do |i| @ractor2.send("Message #{i + 1}") end @ractor2.join end end records = 1_000_000 test = RactorsTest.new(records) p [:once, Benchmark.realtime { test.run1 }.round(2)] p [:all, Benchmark.realtime { test.run2 }.round(2)] ``` **Benchmark Results** On my system, receive_all shows ~4x improvement over individual receive: **Key Observations:** Ractor1 (using receive): Processes each message individually, resulting in frequent I/O calls. Ractor2 (using receive_all): Processes all queued messages at once, minimizing I/O overhead -- https://bugs.ruby-lang.org/