2012-02-24 3 views
0

문제 세부 정보. 다음과 같이 다양한 검사를 수행 할 프레임 워크를 만들어야합니다. - 날짜 B와 날짜 C 사이에 있습니까? - 정수 A가 정수 B보다 크고 정수 C보다 작습니까? 등 지금까지 두 가지 가능한 구현에 대해 생각하고 있습니다. 자세한 내용은 아래를 참조하십시오.속도 프로파일 러 - 인수 유형에 따른 추상 메서드 또는 스위치

Impl1 - 검사 유형을 기반으로 단일 클래스를 사용하여 검사를 수행합니다.

import java.sql.Time; 
import java.util.Date; 

public class SearchManager { 

    public final static int SEARCH_TYPE_DATE = 0; 
    public final static int SEARCH_TYPE_INT = 1; 
    public final static int SEARCH_TYPE_STRING = 2; 
    public final static int SEARCH_TYPE_TIME = 3; 

    private final int searchType; 

    public SearchManager(int searchType) { 
     this.searchType = searchType; 
    } 

    public final boolean doCompare(Object minValue, Object maxValue, Object toBeCompared) { 
     switch (this.searchType) { 
      case SEARCH_TYPE_DATE: { 
       return compareDates((Date) minValue, (Date) maxValue, (Date) toBeCompared); 
      } 
      case SEARCH_TYPE_INT: { 
       return compareIntegers((Integer) minValue, (Integer) maxValue, (Integer) toBeCompared); 
      } 
      case SEARCH_TYPE_STRING: { 
       return compareStrings(String.valueOf(minValue), String.valueOf(maxValue), String.valueOf(toBeCompared)); 
      } 
      case SEARCH_TYPE_TIME: { 
       return compareTimes((Time) minValue, (Time) maxValue, (Time) toBeCompared); 
      } 
      default: 
       return false; 
     } 
    } 

    private boolean compareDates(Date min, Date max, Date toBeCompared) { 
     boolean result = false; 
     // actual comparison 
     return result; 
    } 

    private boolean compareIntegers(Integer min, Integer max, Integer toBeCompared) { 
     boolean result = false; 
     // actual comparison 
     return result; 
    } 

    private boolean compareStrings(String min, String max, String toBeCompared) { 
     boolean result = false; 
     // actual comparison 
     return result; 
    } 

    private boolean compareTimes(Time min, Time max, Time toBeComparedDate) { 
     boolean result = false; 
     // actual comparison 
     return result; 
    } 
} 

Impl2 - 추상 클래스 또는 인터페이스를 사용하고 각 검색 유형에 대해 비교 메소드를 구현합니다. 당신이 상상할 수있는

public abstract class AbstractSearch { 

public final static int SEARCH_TYPE_DATE = 0; 
public final static int SEARCH_TYPE_INT = 1; 
public final static int SEARCH_TYPE_STRING = 2; 
public final static int SEARCH_TYPE_TIME = 3; 

public AbstractSearch() { 
    super(); //just for fun 
} 

protected abstract boolean doCompare(Object minValue, Object maxValue, Object toBeComparedValue); 

}

는 이제,이 예에서, X 다른 검색 유형 들어, AbstractSearch의 X 구현이 생성됩니다.

그냥 2 구현의 클래스 AbstractSearch이 방법 doCompare(..) 이외의 추가 작업을 수행 할 필요가 있다는 자신을 상상하는 인터페이스는이 솔루션에 대한 제 1 후보없는 이유이며,

같은 것을 쓰기
public abstract class AbstractSearch implements Searcheable 

AbstractSearch 또는 SearchManager이 모든 비교를 처리하고, 새로운 비교 유형이 필요하면 추가 유형/서브 클래스 구현이 Impl1 또는 Impl2의 해당 수퍼 클래스에 대해 선언되므로 많은 도움이되지 않습니다.

제 질문은 어떤 구현이 더 빠릅니까? 비교 프로세스는 수천 개의 요소가 포함 된 루프에서 호출되므로 매우 중요합니다. 내 질문을 읽고 답변 해 주셔서 감사합니다.

EDIT1 : 또한, MINVALUE 경우 MAXVALUE은 첫번째 예로서, SearchManager 연장 제, 예를 들면, AbstractSearch 확장 클래스 또는 클래스로부터 추출 될 것이라는 사실을 염두에두고주세요. 이러한 구현은 실제로 사용자가 최소값과 최대 값을 입력 할 수있게 해주는 그래픽 구성 요소가 될 것이고이 값은 루프에서 테이블에 표시된 객체의 일부 빈 특성과 비교됩니다.

EDIT2 : 더미 구현 (나는 단지 메서드 호출 시간 대 스위치 실행 시간 비교)을 사용하여 벤치 마크를 수행하고 있습니다. 결과는 are..surprising : -0.047 초 SearchManager를 사용

  • (50 만 개 루프) :

    • 이 AbstractSearch (50 만 개 루프)를 사용하여 -0.422 초

    이러한 결과를 갖는, 그것은에 안전 상속을 사용하는 것이 스위치를 사용하는 것보다 훨씬 더 빠르다고 가정합니다 (또는 if-else 테스트를 더 나쁘게 생각할 수도 있습니다)?

  • +0

    'AbstractManager'가이기는 것은 놀라운 일이 아닙니다. 상속 된 메소드를 호출하면 메소드 테이블에서 함수 포인터를 가져 와서 호출해야하지만'switch '에는 여러 비교와 분기가 필요합니다 (파이프 라인이 멈출 수 있습니다. CPU는 분기가 어느 방향으로 갈 것인지 정확하게 추측 할 수 없습니다). –

    답변

    1

    하기이 같은 오버로드 된 메서드를 사용해보십시오, 가능한 한 빨리이 코드를 확인하려면 : 컴파일시에

    public final static boolean doCompare(Date min, Date max, Date toCompare) { 
        // ... 
    } 
    public final static boolean doCompare(int min, int max, int toCompare) { 
        // ... 
    } 
    // ...and so on 
    

    , 컴파일러는에 따라 적절한 방법을 직접 호출을 생성합니다 당신이 통과하는 타입. (4 가지 유형의 인스턴스를 가리킬 수있는 객체 참조를 전달하는 경우 작동하지 않습니다.)

    비교할 값이 int이면 Object 인수는 복싱과 언 박싱을 필요로하므로 오버 헤드가 추가됩니다.

    성능이 중요한 경우 많은 Java 구현에서 조금 더 빠르기 때문에 static 메서드를 사용하는 것이 좋습니다.

    또한 compareTo을 사용하는 대신 비교를 위해 사용자 고유의 인라인 코드를 사용하여 성능을 약간 조정할 수 있습니다.

    편집 : 당신은 minmax 실제로 서브 클래스 SearchManager에 의해 전달 될 것이라고 편집 된 질문했다. 이 경우 SearchManagerabstract을 만들고 SearchManager의 각 하위 클래스에 doCompare의 다른 구현을 넣습니다. 이 경우에는 static 메서드에 대해 언급 한 내용이 작동하지 않습니다.

    +0

    그건 정확히 내가 생각한 것이지만, 다른 의견을들을 필요가있었습니다. 귀하의 인내심과 의견을 위해 최선의 선택을드립니다. 축하와 감사. – hypercube

    0

    비교로 할 수있는 것입니까? (이 모양은 비슷합니다.)이 메소드는 세 가지 구현 모두에서 본질적으로 동일합니까?

    때문에, 단지

    static <T extends Comparable<T>> boolean doCompare(T min, T max, T toCompare) { 
        // impl here 
    } 
    
    1
    내가 가장 좋은 아이디어는 모두 아이디어를 결합 (그리고 더 많은 종류 안전하게)하는 것이라고 생각

    를 작성하고 모든 유형의 사용자가 제공한다는 사실을 활용하는 경우 당신의 예에서 (날짜, 시간, 문자열 및 정수)이 확실히 훨씬 빨리 첫 번째 구현 때보 다 모든 종류의 검사를 할 필요가 없기 때문에입니다

    public final <A> boolean doCompare (Comparable<A> min, Comparable<A> max, A target) 
    { 
        return (min.compareTo(target) < 0) && (max.compareTo(target) > 0) 
    } 
    

    이 Comparable (모든 검사는 컴파일 시간을 할 것입니다)보다 안전하고 두 번째 속도보다 빠르지 않습니다 (als o 유형에 대해 더 유연함).

    0

    재미있는 질문! 두 가지 구현을 벤치마킹 해 보시지 않겠습니까?

    +0

    나는 우리가 말하는 것처럼 그렇게하고있다. 그러나 나는 모든 대답을 가지고 있다고 생각하지 않는다. 아마도 여기에있는 누군가가 완전히 다른 구현 방식을 사용하게 될 것입니다. 이는 내 시나리오보다 우수합니다. – hypercube