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

Daniel Harvey dharvey at tachyoncm.com
Mon Aug 11 12:30:54 EDT 2008


I've tried a number of the above suggestions.

1) The prespinTake degraded the performance a little further, and I  
think suggests that it is not waking the blocked thread that is  
causing the delay.
2) Draining the queue into an ArrayList (Carfield's suggestion) may  
have slightly improved things, but not significantly (a few % maybe).
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.

Having run the tests more times, and for longer duration, I  
apparently overstated the degradation that is caused by the consumer  
executing the socket.write() (in addition to performing the  
encoding):  it appears to be a factor of 3 and not 6. Nevertheless,  
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);
}

I still intend to experiment with different JVMs and also to try  
Jed's SRSW code.

Many thanks for all the suggestions so far!

-Dan


On Aug 10, 2008, at 6:46 PM, David Holmes wrote:

> Hi Doug,
>
> But in this case removing the network load in the consumer causes the
> consumer to execute take() more rapidly and so it is more likely to  
> find the
> queue empty, and so block. But this is the case that appears 6x  
> faster. ???
>
> David
>
>> -----Original Message-----
>> From: concurrency-interest-bounces at cs.oswego.edu
>> [mailto:concurrency-interest-bounces at cs.oswego.edu]On Behalf Of  
>> Doug Lea
>> Sent: Sunday, 10 August 2008 1:16 AM
>> To: Daniel Harvey
>> Cc: concurrency-interest at cs.oswego.edu
>> Subject: Re: [concurrency-interest] Single producer, single consumer:
>> unexpected delays for producer
>>
>>
>> Daniel Harvey wrote:
>>>
>>> What is so odd to me is that 90% of the total time spent in  
>>> onMessage()
>>> comes from time spent in queue.offer() despite the fact that this is
>>> only called for 20% of the messages. If I have the sendThread  
>>> skip the
>>> socketChannel.write() command, than the situation changes  
>>> greatly: time
>>> spent in queue.offer drops by a literally a factor of 6 or so.
>>>
>>
>> This may be due to slow thread unblocking in your VM.
>> You can try to avoid this a bit by pre-spinning on take:
>>
>> String prespinTake(BlockingQueue<String> q) {
>>    for (int i = 0; i < SPINS; ++i) {
>>      String x = q.poll();
>>      if (x != null)
>>         return x;
>>    }
>>    return q.take();
>> }
>>
>> where SPINS is a number say between 1 and 1000.
>> This will avoid offer() needing to wake up a blocked take thread.
>>
>> -Doug
>> _______________________________________________
>> Concurrency-interest mailing list
>> Concurrency-interest at cs.oswego.edu
>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>



More information about the Concurrency-interest mailing list