2014-01-26 4 views
0

Disruptor API의 가장 기본적인 주장에 대한 제 질문에 대해 알고 있습니다. 그러나 그것에 대해 배우면서 ArrayLinkedBlockingQueue를 사용하여 1P-1C 사용법을 대체하는 프로그램을 작성했습니다. 그러나 프로그램을 실행하면서, 나는 Disruptor로 가져간 총 시간을 ArrayLinkedBlockingQueue보다 나 빠졌습니다. 나는 틀린 일을하고 있거나 잘못 측정 한 것이 틀림 없다. 그러나 나는 그것이 내 프로그램에 무엇인지 확신 할 수 없다. 누구 의견이 있습니까?Disruptor의 성능 향상을 보지 못했습니다.

당신은 실제로 잘못을 측정하는

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() { 
     } 

    } 
} 
+0

나는 내 컴퓨터에서 코드를 시도 할 때마다 방해물이 더 좋은 결과를 얻고 있습니다. 나는 더 작은 버퍼 크기를 사용했다. – Edge

답변

0

(너무 분명 내 이벤트 핸들러는 아무것도하지 않는 테스트 프로그램입니다). 워밍업 (링 버퍼 할당)에 시간이 걸리므로 중단기를 시작한 후에 측정을 시작해야합니다. 버퍼 크기가 커지면 워밍업에 많은 시간이 걸립니다. 아래 샘플 코드를 시도하십시오. 그것은 당신에게 더 좋은 시간을 줄 것입니다.

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); 
+0

불행하게도 나는 많은 차이를 보지 못했다. 오래된 접근 방법으로 disruptor가 걸렸습니다 : 2.93E7 ms disruptor.start() 이후 시간을 추적하면 2.6E7 ms가됩니다. 이렇게 많은 차이가 없습니다 ... – endless

관련 문제