2012-01-23 5 views
0

키 기능은 다른 시스템의 데이터를 최대한 빨리 (차단하지 않고) 받아들이는 것입니다. 내 응용 프로그램은 나중에 데이터를 처리합니다.LinkedBlockingQueue에서 put()의 성능

그렇다면 내가 메시지를 LinkedBlockingQueue/LinkedTransferQueue에 큐에 대기시킨 다음 주기적으로 큐를 비우고 백그라운드 스레드에서 데이터를 처리하는 것이 었습니다.

private final LinkedTransferQueue<Data> queue = new LinkedTransferQueue<Data>(); 

    public void store(int index, long time, String[] data) throws InterruptedException{ 
     Data data = new Data(index, time, data); 
     queue.put(data); 
    } 

    private class BackgroundProcessor implements Runnable{ 

    private List<Data> entryList = new LinkedList<Data>(); 

    @Override 
    public void run(){ 

     try { 
      while (keepProcessing){ 

       int count = queue.drainTo(entryList); 

       for (Data data : entryList){ 
       //process data 
       } 
      } 
     } catch(Exception e){ 
       logger.error("Exception while processing data.", e); 
     } 
    } 

} 

내가 다음이 방법의 성능을 테스트하고 싶었 :의 라인을 따라

그래서 뭔가

public void testStore(String[] dataArray) throws InterruptedException{ 

     int size = 100 * 1000; 

     long iTime = System.nanoTime(); 
     for (int i=0; i < size; i++){ 
      store(i, System.nanoTime, dataArray); 
     } 
     long fTime = System.nanoTime(); 

     System.err.println("Average Time (nanos): " + (fTime - iTime)/size; 

     float avgTimeInMicros = ((float) (fTime - iTime)/(size * 1000)); 
     System.err.println("Average Time (micros): " + avgTimeInMicros); 
    } 

내가 볼을 나의 testStore()에서, 크기 = 100의 경우, 0000, 나는 불변의 객체 인 Data 객체를 만들고 0.8 마이크로 초 안에 대기시킬 수 있습니다. 그러나 크기를 50으로 줄이면 20 마이크로가 필요합니다.

잠시 후 jvm을 사용하면 코드가 최적화됩니다. 그러나, 내 응용 프로그램에서 버스트 크기에 상관없이 1-2 개의 마이크로 메시지를 대기열에 넣기 위해 jvm (또는 내 코드)을 조정할 수있는 방법이 있습니까?

P.S jmk 1.6에서 -mx == -ms 512m으로이 테스트를 시도했습니다.

+2

퍼포먼스를 타이밍하는 방법을 잘 모르겠지만 타이밍을 시작하기 전에 "펌프 준비 완료"가 있어야합니다. 즉, JVM이 처음으로 새로운 클래스를로드 할 때 시간이 손실된다는 것을 의미합니다. 이 클래스 로딩 시간은 적은 수의 메시지를 측정하는 것에 비례하여 중요합니다. 테스트를 약 1,000 회 반복 실행 한 다음 50 개의 메시지를 시뮬레이트합니다. 이것은 결과가 JVM 시작/클래스 로딩에 의해 왜곡되지 않도록합니다. 일반적으로 Java에서 간헐적 인 처리를 위해 일정한 성능 시간을 보장하는 것은 어려운 작업입니다. –

+0

위의 의견에 완전히 동의하십시오. 당신은 순진한 마이크로 벤치 마크입니다. Goetz가 읽어야 할이 기사를보십시오 : http://www.ibm.com/developerworks/java/library/j-jtp02225/index.html –

+0

고마워요. 실제 데이터가 삽입되기 전에 대기열을 예열합니다. 결과적으로 50 개의 메시지로 이루어진 연속 된 버스트가 약 2 마이크로 초 대기열에 포함됩니다. – CaptainHastings

답변

1

10,000을 처리 한 다음 JVM이 예열 된 후 버스트가 50인지 테스트합니다. 거래 시스템의 경우 거래를 시작하기 전에 JVM이 예열되었는지 확인해야합니다.

거래 시스템을 일관되게 빨리 만들고 싶다면 어떤 물건을 버리지 않고 어떻게 할 수 있는지 생각할 수 있습니다.

흥미있는 Disruptor 라이브러리를 찾을 수 있습니다. 초당 5M 메시지를 처리하도록 설계되었습니다. http://code.google.com/p/disruptor/

+0

안녕하세요 피터, 나는 그것이 특정 직업의 과잉 일지 모르지만 장애가있는 도서관과 환상적인 곳을 보았습니다. 생산자를 수용 할 수없는 방법이 있는지 알고 있습니까? (나는 그들이 대기 중 (락, 스핀 등)의 맛을 선택할 수있는 "ClaimStrategy"의 다른 변형을 가지고 있음을 안다.) 건배 – CaptainHastings

+0

생산자를 안고있는 문제는 큐를 효율적으로 성장시켜야하는 경우가 종종있다. 큰 대기열을 사용하면 이점이 누적됩니다.이 문제를 해결하는 방법은 디스크 공간만큼 커질 수있는 공유 메모리를 사용하는 것입니다. 빠른 디스크 (예 : SSD)를 사용하면 최소한의 메시지만으로 수백만 메시지를 전달할 수 있습니다 충격. –