Java BlockingQueue latency high on Linux

后端 未结 4 1837
终归单人心
终归单人心 2021-01-30 23:03

I am using BlockingQueue:s (trying both ArrayBlockingQueue and LinkedBlockingQueue) to pass objects between different threads in an application I’m currently working on. Perform

4条回答
  •  余生分开走
    2021-01-30 23:12

    @Peter Lawrey

    Certain operations use OS calls (such as locking/cyclic barriers)

    Those are NOT OS (kernel) calls. Implemented via simple CAS (which on x86 comes w/ free memory fence as well)

    One more: dont use ArrayBlockingQueue unless you know why (you use it).

    @OP: Look at ThreadPoolExecutor, it offers excellent producer/consumer framework.

    Edit below:

    to reduce the latency (baring the busy wait), change the queue to SynchronousQueue add the following like before starting the consumer

    ...
    consumerThread.setPriority(Thread.MAX_PRIORITY);
    consumerThread.start();
    

    This is the best you can get.


    Edit2: Here w/ sync. queue. And not printing the results.

    package t1;
    
    import java.math.BigDecimal;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.SynchronousQueue;
    
    public class QueueTest {
    
        static final int RUNS = 250000;
    
        final SynchronousQueue queue = new SynchronousQueue();
    
        int sleep = 1000;
    
        long[] results  = new long[0];
        public void start(final int runs) throws Exception {
            results = new long[runs];
            final CountDownLatch barrier = new CountDownLatch(1);
            Thread consumerThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    barrier.countDown();
                    try {
    
                        for(int i = 0; i < runs; i++) {                        
                            results[i] = consume(); 
    
                        }
                    } catch (Exception e) {
                        return;
                    } 
                }
            });
            consumerThread.setPriority(Thread.MAX_PRIORITY);
            consumerThread.start();
    
    
            barrier.await();
            final long sleep = this.sleep;
            for(int i = 0; i < runs; i++) {
                try {                
                    doProduce(sleep);
    
                } catch (Exception e) {
                    return;
                }
            }
        }
    
        private void doProduce(final long sleep) throws InterruptedException {
            produce();
        }
    
        public void produce() throws InterruptedException {
            queue.put(new Long(System.nanoTime()));//new Long() is faster than value of
        }
    
        public long consume() throws InterruptedException {
            long t = queue.take();
            long now = System.nanoTime();
            return now-t;
        }
    
        public static void main(String[] args) throws Throwable {           
            QueueTest test = new QueueTest();
            System.out.println("Starting + warming up...");
            // Run first once, ignoring results
            test.sleep = 0;
            test.start(15000);//10k is the normal warm-up for -server hotspot
            // Run again, printing the results
            System.gc();
            System.out.println("Starting again...");
            test.sleep = 1000;//ignored now
            Thread.yield();
            test.start(RUNS);
            long sum = 0;
            for (long elapsed: test.results){
                sum+=elapsed;
            }
            BigDecimal elapsed = BigDecimal.valueOf(sum, 3).divide(BigDecimal.valueOf(test.results.length), BigDecimal.ROUND_HALF_UP);        
            System.out.printf("Avg: %1.3f micros%n", elapsed); 
        }
    }
    

提交回复
热议问题