I don't have any special expertise in or experience with this, I'm just
trying to draw logical inferences from what others have written.

Stated:

 - From a semantic perspective the only distinction is between bounded and
unbounded queues. The capacity of a bounded queue only makes a difference
with regards to performance.

 - There is also no such thing as an unbounded queue. The only distinction
is between queues whose capacities are constrained by us, and fail
predictably, and queues whose capacities are constrained by the available
resources, and fail chaotically.

 - The storage for a bounded queue need not all be allocated up-front, this
also just a performance optimization (or pessimization).

The big difference is in the user of the queue and the use case. Some users
in some cases don't want to have to think about the possibility of failure,
either because they believe that it's extremely unlikely or impossible (the
producer is only ever going to send 100 messages, no way it's going to
exhaust resources), and/or because failure is not a big problem for them
(we can just restart the thing, and putting in the effort to rule failure
out up-front doesn't pass the cost-benefit test). Other users in other
cases believe failure is a serious consideration and they want to be able
to prevent it or handle it well.

Assuming that we want to continue catering foremost to the people who don't
want to think about failure, but also don't want to leave the people who do
want to think about it out in the cold, what about:

 - Having only one type of queue, which is bounded,

 - and whose default capacity is just small enough that it would be hit
before exhausting resources, but is otherwise still ridiculously large
("effectively unbounded") (so basically what Kevin wrote),

 - failing the task on `send()` if the capacity would be exceeded,

 - allowing a smaller capacity (down to 1) to be specified instead,

 - also providing a try_send() method which returns false/Err, instead of
failing, when there is no available capacity,

 - and using a different representation for the queue storage for different
capacity classes: e.g. allocating up-front if it's "small" and growing it
incrementally if it's "large"?

The last point is speculative: I don't know if bounded and "effectively
unbounded" queues can both be implemented performantly in a single type.

Anyway: could this work?


On Thu, Dec 19, 2013 at 7:23 PM, Kevin Ballard <[email protected]> wrote:

> Here’s an example from where I use an infinite queue.
>
> I have an IRC bot, written in Go. The incoming network traffic of this bot
> is handled in one goroutine, which parses each line into its components,
> and enqueues the result on a channel. The channel is very deliberately made
> infinite (via a separate goroutine that stores the infinite buffer in a
> local slice). The reason it’s infinite is because the bot needs to be
> resilient against the case where either the consumer unexpectedly blocks,
> or the network traffic spikes. The general assumption is that, under normal
> conditions, the consumer will always be able to keep up with the producer
> (as the producer is based on network traffic and not e.g. a tight CPU loop
> generating messages as fast as possible). Backpressure makes no sense here,
> as you cannot put backpressure on the network short of letting the socket
> buffer fill up, and letting the socket buffer fill up with cause the IRC
> network to disconnect you. So the overriding goal here is to prevent
> network disconnects, while assuming that the consumer will be able to catch
> up if it ever gets behind.
>
> This particular use case very explicitly wants a dynamically-sized
> infinite channel. I suppose an absurdly large channel would be acceptable,
> because if the consumer ever gets e.g. 100,000 lines behind then it’s in
> trouble already, but I’d rather not have the memory overhead of a
> statically-allocated gigantic channel buffer.
>
> -Kevin
>
> On Dec 19, 2013, at 10:04 AM, Jason Fager <[email protected]> wrote:
>
> Okay, parallelism, of course, and I'm sure others.  Bad use of the word
> 'only'.  The point is that if your consumers aren't keeping up with your
> producers, you're screwed anyways, and growing the queue indefinitely isn't
> a way to get around that.  Growing queues should only serve specific
> purposes and make it easy to apply back pressure when the assumptions
> behind those purposes go awry.
>
>
> On Thursday, December 19, 2013, Patrick Walton wrote:
>
>> On 12/19/13 6:31 AM, Jason Fager wrote:
>>
>>> I work on a system that handles 10s of billions of events per day, and
>>> we do a lot of queueing.  Big +1 on having bounded queues.  Unbounded
>>> in-memory queues aren't, they just have a bound you have no direct
>>> control over and that blows up the world when its hit.
>>>
>>> The only reason to have a queue size greater than 1 is to handle spikes
>>> in the producer, short outages in the consumer, or a bit of
>>> out-of-phaseness between producers and consumers.
>>>
>>
>> Well, also parallelism.
>>
>> Patrick
>>
>> _______________________________________________
>> Rust-dev mailing list
>> [email protected]
>> https://mail.mozilla.org/listinfo/rust-dev
>>
>  _______________________________________________
> Rust-dev mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/rust-dev
>
>
>
> _______________________________________________
> Rust-dev mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/rust-dev
>
>
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to