[concurrency-interest] Single producer, single consumer: unexpected delays for producer

Daniel Harvey dharvey at tachyoncm.com
Tue Aug 12 14:55:51 EDT 2008


Having tested today, I found that performing:
for (;;) queue.take();
causes very little more contention that the best scenario, and much  
less than when the socket.write() is being performed.

On Aug 11, 2008, at 8:50 PM, David Holmes wrote:

> Dan,
>
> Your second case isn't a continuous take() because it does:
>
> ByteBuffer bytes = encoder.encode(chars);
>
> that might take sufficient time for the producer to produce the  
> next item
> (or two) with no contention.
>
> That's why I said that I would expect:
>
> for(;;) queue.take();
>
> to also cause maximum contention.
>
> David
>
>> -----Original Message-----
>> From: Daniel Harvey [mailto:dharvey at tachyoncm.com]
>> Sent: Tuesday, 12 August 2008 10:48 AM
>> To: dholmes at ieee.org
>> Cc: concurrency-interest at cs.oswego.edu
>> Subject: Re: [concurrency-interest] Single producer,single consumer:
>> unexpected delays for producer
>>
>>
>> I'm not sure whether the queue size is non-zero in the fast case,
>> though I will test this tomorrow and report back. But something
>> doesn't make sense here because in the second case -  the continuous
>> take() one - there should be an even greater likelihood of
>> encountering a non-empty queue... I really feel like the issue has to
>> be the socket write interfering with the thread-signaling of the
>> existence of a new message to process: I'm fairly sure that I could
>> add other time-taking calculations to the consumer thread (in place
>> of the socket.write() ) and they wouldn't slow down the producer.
>> I'll add something like this tomorrow and see whether my assessment
>> is accurate.
>>
>> The following isn't a very elegant solution, and it might hammer the
>> CPU too much, but I have experimented with having the consumer do a
>> periodic sending of a batch of messages, then sleeping and checking
>> for new messages every few ms (rather than waiting), and repeating.
>> With this approach there's no signal between threads and I think the
>> producer operates much faster (even with the necessary
>> synchronization). Of course I am adding latency, but if throughput is
>> the bottom line, it might be a useable solution.
>>
>> -Dan
>>
>> On Aug 11, 2008, at 8:29 PM, David Holmes wrote:
>>
>>> Dan,
>>>
>>>> 3) I put some code in to keep track of how many messages are
>>>> typically in the queue when the consumer thread finishes it's  
>>>> take(),
>>>> and it is typically 0... ie the majority (around 80-90%) of the  
>>>> time
>>>> a single message is being removed from the queue.
>>>
>>> Okay so that explains the contention. The producer is expending  
>>> effort
>>> acquiring two locks and waking up the producer.
>>>
>>>> that's still a big difference... specifically:
>>>>
>>>> for (;;) {
>>>> 	CharBuffer chars = CharBuffer.wrap(queue.take());
>>>> 	ByteBuffer bytes = encoder.encode(chars);
>>>> 	socketChannel.write(bytes);
>>>> }
>>>>
>>>> causes queue.offer(message) to take 3 times longer to execute  
>>>> than if
>>>> the consumer executes:
>>>>
>>>> for (;;) {
>>>> 	CharBuffer chars = CharBuffer.wrap(queue.take());
>>>> 	ByteBuffer bytes = encoder.encode(chars);
>>>> }
>>>
>>> Can I assume that in the fast case the queue size is not normally
>>> zero? If
>>> so my theory here is that when the consumer uses the socketChannel
>>> it is
>>> introducing additional contention with the prodcuer that keeps the
>>> producer
>>> and conumer effectively in lock-step:
>>> - consumer blocks on take()
>>> - producer gets item and does offer() and has to wakeup consumer
>>> - consumer processes item and uses resources needed by producer
>>> - producer is blocked or delayed getting next item
>>> - consumer calls take() again and blocks
>>> - producer produces and calls offer() and has to wakeup consumer
>>> - repeat
>>>
>>> However in that case I would expect:
>>>   for(;;) queue.take();
>>> to also impose maximum contention with the producer.
>>>
>>> David
>>>
>>
>



More information about the Concurrency-interest mailing list