簡體   English   中英

我看不到Disruptor的性能提升

[英]I don't see the performance improvement of Disruptor

我知道我的問題與Disruptor API的根本主張背道而馳。 但是,當我學習它時,我寫了一個程序來替換我在使用ArrayLinkedBlockingQueue的1P-1C用例。 但是,當我運行程序時,與ArrayLinkedBlockingQueue相比,我使干擾器花費的總時間更糟。 我一定做錯了或度量錯誤,但是我不確定程序中的內容。 有人有意見嗎?

(這是一個測試程序,因此顯然我的EventHandler沒有執行任何操作)

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lmax.disruptor.BusySpinWaitStrategy;
import com.lmax.disruptor.EventFactory;
import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.EventTranslator;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;

public class SPSCDisruptorTest {
    private static final int UNIT_SIZE = 1024;
    private static final int BUFFER_SIZE = UNIT_SIZE * 1024 * 16;
    private static final int ITERATIONS = BUFFER_SIZE;
    private static final Logger logger = LoggerFactory
            .getLogger(SPSCDisruptorTest.class);

    private static class Data {
        private String data;

        public String getData() {
            return data;
        }

        public void setData(String data) {
            this.data = data;
        }

        @Override
        public String toString() {
            return "Data [data=" + data + "]";
        }

        public final static EventFactory<Data> DATA_FACTORY = new EventFactory<Data>() {

            @Override
            public Data newInstance() {
                return new Data();
            }

        };
    }

    private static class DataEventTranslator implements EventTranslator<Data> {
        private String payload;

        public DataEventTranslator(String payload) {
            this.payload = payload;
        }

        @Override
        public void translateTo(Data d, long sequence) {
            d.setData(payload);
        }

    };

    public static void main(String[] args) throws InterruptedException {
        new SPSCDisruptorTest().testDisruptor();
        new SPSCDisruptorTest().testExecutor();
    }

    @SuppressWarnings("unchecked")
    public void testDisruptor() {
        ExecutorService exec = Executors.newSingleThreadExecutor();
        Disruptor<Data> disruptor = new Disruptor<Data>(
                SPSCDisruptorTest.Data.DATA_FACTORY, BUFFER_SIZE, exec,
                ProducerType.SINGLE, new BusySpinWaitStrategy());
        disruptor.handleEventsWith(new EventHandler<Data>() {

            @Override
            public void onEvent(Data data, long sequence, boolean endOfBatch)
                    throws Exception {
            }

        });
        long t1 = System.nanoTime();
        RingBuffer<Data> buffer = disruptor.start();
        for (int i = 1; i <= ITERATIONS; i++) {
            buffer.publishEvent(new DataEventTranslator("data" + i));
        }
        logger.info("waiting for shutdown");
        disruptor.shutdown();
        logger.info("Disruptor Time (ms): " + (System.nanoTime() - t1 * 1.0)
                / 1000);
        logger.info("Disruptor is shutdown");
        exec.shutdown();
    }

    public void testExecutor() throws InterruptedException {
        ExecutorService executor = new ThreadPoolExecutor(1, 1, 0L,
                TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(
                        BUFFER_SIZE));
        long t1 = System.nanoTime();
        for (int i = 1; i <= ITERATIONS; i++) {
            executor.submit(new DataRunner("data" + i));
        }
        executor.shutdown();
        executor.awaitTermination(5000, TimeUnit.SECONDS);
        logger.info("Executor Time (ms): " + (System.nanoTime() - t1 * 1.0)
                / 1000);
    }

    private static class DataRunner implements Runnable {
        private String data;

        public DataRunner(String data) {
            this.data = data;
        }

        @Override
        public void run() {
        }

    }
}

您實際上是在測量錯誤。 啟動干擾器后,應該開始測量,因為它需要花費一些時間進行預熱(分配環形緩沖區)。 由於緩沖區很大,因此預熱需要花費大量時間。 請嘗試下面的示例代碼。 它應該給您更好的時間。

    RingBuffer<Data> buffer = disruptor.start();
    long t1 = System.nanoTime();
    for (int i = 1; i <= ITERATIONS; i++) {
        buffer.publishEvent(new DataEventTranslator("data" + i));
    }
    logger.info("waiting for shutdown");
    disruptor.shutdown();
    logger.info("Disruptor Time (ms): " + (System.nanoTime() - t1 * 1.0)
            / 1000);

您沒有足夠的爭論來說明無鎖干擾器如何提供幫助。 特別是,您的執行者隊列與迭代一樣大! 所有數據都適合執行程序隊列,因此它基本上絕不會在非空/非滿條件下運行。

執行器服務也確實很糟糕,因為如果隊列較小,您將拒絕執行。 您需要比較的是2個線程和一個有限隊列(可能長1000)並阻塞了.put()/。take()調用。

更糟糕的是,您需要成批的數據(而不是1比1),並且需要許多讀者,甚至可能需要很多作家。 通過對執行程序測試進行競爭的隊列訪問,中斷程序應該毫無問題地顯示其性能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM