Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

busy spin to reduce context switch latency (java)

In my application there are several services that process information on their own thread, when they are done they post a message to the next service which then continue to do its work on its own thread. The handover of messages is done via a LinkedBlockingQueue. The handover normally takes 50-80 us (from putting a message on the queue until the consumer starts to process the message). To speed up the handover on the most important services I wanted to use a busy spin instead of a blocking approach (I have 12 processor cores and want to dedicate 3 to these important services). So.. I changed LinkedBlockingQueue to ConcurrentLinkedQueue

and did

for(;;)
{
 Message m = queue.poll();
 if( m != null )
  ....
}

Now.. the result is that the first message pass takes 1 us, but then the latency increases over the next 25 handovers until reaches 500 us and then the latency is suddenly back to 1 us and the starts to increase.. So I have latency cycles with 25 iterations where latency starts at 1 us and ends at 500 us. (message are passed approximately 100 times per second)

with an average latency of 250 it is not exactly the performance gain I was looking for.

I also tried to use the LMAX Disruptor ringbuffer instead of the ConcurrentLinkedQueue. That framwork have its own build in busy spin implementation and a quite different queue implementation, but the result was the same. So im quite certain that its not the fault of the queue or me abusing something..

Question is.. What the Heck is going on here? Why am I seeing this strange latency cycles?

Cheers!!

like image 598
Pontus Jörgne Avatar asked Jan 04 '13 12:01

Pontus Jörgne


1 Answers

As far as I know thread scheduler can deliberately pause a thread for a longer time if it detects that this thread is using CPU quite intensively - to distribute CPU time between different threads fairer. Try adding LockSupport.park() in the consumer after queue is empty and LockSupport.unpark() in the producer after adding the message - it might make the latency less variable; whether it will actually be better comparing to blocking queue is a big question though.

like image 197
Andrey Nudko Avatar answered Nov 20 '22 06:11

Andrey Nudko