Here is my scenario¹. I have a producer consumer system that is composed by two producers, one consumer, and a bounded Channel<T>
configured with capacity 2. The T
is byte[]
.
Channel<byte[]> channel = Channel.CreateBounded<byte[]>(2);
The byte[]
s propagated through the channel are huge (1GB each), which creates the need to limit the total number of the arrays that exist at any given moment to a minimum. So the two producers are waiting before creating a new byte[1_000_000_000]
, until they know that there is empty space in the channel. Here is the first producer:
Task producer1 = Task.Run(async () =>
{
while (true)
{
await channel.Writer.WaitToWriteAsync();
// The channel has space available. Let's create the array.
byte[] array = new byte[1_000_000_000];
// Here initialize the array (mainly I/O bound, time consuming)
// At this moment the channel might be full,
// because the other producer filled the gap.
await channel.Writer.WriteAsync(array);
}
});
The second producer is identical. Unfortunately this allows both producers to start creating a new array, even when there is only one empty slot in the channel. So at some moment the system might have 4 huge arrays alive at the same time: 1 consumed by the consumer, 1 stored in the channel, and 2 created concurrently be the two producers (trying to fill a single empty slot).
I want to limit the total number of arrays in managed memory to 3. Is there any way that I can tame my producers, so that they don't start creating a new byte[]
until there is certainly space available for it in the channel? In other words after creating an array, the producer should be able to write it immediately in the channel like this:
bool success = channel.Writer.TryWrite(array);
...and the success
should always be true
.
¹ This scenario is contrived. It was inspired by a recent GitHub issue.
Clarification: The construction and initialization of the byte arrays is the exclusive responsibility of the producer, and it should stay this way. Delegating the construction work elsewhere, either partially or fully, is not desirable.