문제

나는 방금 내가이 시점에 어떻게 도달했는지에 대한 전체 블러브를 썼지 만, 코드를 게시하고 그것을 남겨 두는 것이 더 쉽다고 생각했다 :)

내가 알 수있는 한, test3 ()의 성능은 test1 ()과 동일해야합니다 - 유일한 차이점은 예외가 잡힌 곳입니다 (test3 ()의 호출 메소드 내부에서 test1 ()의 호출 방법 내부).

test3 ()가 정기적으로 test1 ()과 test2 () 사이에서 시간을 정기적으로 완료하려면 시간이 정기적으로 시간이 걸리나요?

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

public class Test {

    public static void main(String[] args) {
        warmup(); 
        test1(2500000); // Exception caught inside the loop
        test2(2500000); // Exception caught outside the loop
        test3(2500000); // Exception caught "inside" the loop, but in the URLEncoder.encode() method
    }

    private static void warmup() {
        // Let URLEncoder do whatever startup it needs before we hit it
        String encoding = System.getProperty("file.encoding");
        try {
            URLEncoder.encode("ignore", encoding);
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private static void test1(int count) {
        String encoding = System.getProperty("file.encoding");
        long start = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            try {
                URLEncoder.encode("test 1 " + i, encoding);
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("Performed " + count + " encodings trying to catch each in " + (end - start) + "ms");
    }

    private static void test2(int count) {
        String encoding = System.getProperty("file.encoding");
        long start = System.currentTimeMillis();
        try {
            for (int i = 0; i < count; i++) {
                URLEncoder.encode("test 2" + i, encoding);
            }
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("Performed " + count + " encodings trying to catch all in " + (end - start) + "ms");
    }

    private static void test3(int count) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            URLEncoder.encode("test 3 " + i);
        }
        long end = System.currentTimeMillis();
        System.out.println("Performed " + count + " encodings with a deprecated method in " + (end - start) + "ms");
    }

}

실행 그것은 나에게 제공합니다 (JDK 1.6.0_13 Windows XP에서) 출력 :

Performed 2500000 encodings trying to catch each in 4906ms
Performed 2500000 encodings trying to catch all in 2454ms
Performed 2500000 encodings with a deprecated method in 2953ms

그래서, 반응은 꽤 가깝습니다 (우리는 너무 사소한 말을하고 있습니다), btu 나는 궁금합니다!

나중...

사람들은 JVM 최적화가 방해가되고 있다고 제안했습니다. 그래서 각 테스트를 자체 클래스/메인 방법과 개별적으로 분해했습니다. 이것의 결과 :

1 - Performed 2500000 encodings trying to catch each in 5016ms
1 - Performed 5000000 encodings trying to catch each in 7547ms
1 - Performed 5000000 encodings trying to catch each in 7515ms
1 - Performed 5000000 encodings trying to catch each in 7531ms

2 - Performed 2500000 encodings trying to catch all in 4719ms
2 - Performed 5000000 encodings trying to catch all in 7250ms
2 - Performed 5000000 encodings trying to catch all in 7203ms
2 - Performed 5000000 encodings trying to catch all in 7250ms

3 - Performed 2500000 encodings with a deprecated method in 5297ms
3 - Performed 5000000 encodings with a deprecated method in 8015ms
3 - Performed 5000000 encodings with a deprecated method in 8063ms
3 - Performed 5000000 encodings with a deprecated method in 8219ms

흥미로운 관찰 :

  • 각 통화를 잡는 것과 루프 외부의 모든 것을 잡는 것 사이의 간격은 자체 JVM에서 줄어 듭니다 (나는 최적화가 수행 된 다른 반복으로 인해 모든 테스트에서 모든 돼지를 사용하지 않는다고 가정합니다).
  • urlencoder.encode () 내부의 시도/캐치 사이의 시도/캐치 사이의 간격은 이제 훨씬 작지만 (5000000 개 이상의 반복)는 여전히 ...
도움이 되었습니까?

해결책

게시 한 순서대로 실행합니다.

34208ms에서 각각을 잡으려고 2500000 인코딩을 수행했습니다
31708ms에서 모든 것을 잡으려고 2500000 인코딩을 수행했습니다
30738ms에서 더 이상 사용되지 않은 방법으로 2500000 인코딩을 수행했습니다

순서를 되돌리기 :

32598ms에서 더 이상 사용되지 않은 방법으로 2500000 인코딩을 수행했습니다
31239ms에서 모든 것을 잡으려고 2500000 인코딩을 수행했습니다
31208ms에서 각각을 잡으려고 2500000 인코딩을 수행했습니다

따라서 나는 당신이 당신이보고있는 것을 실제로보고 있다고 생각하지 않습니다 (확실히, test1은 test3보다 66% 느리지 않습니다. 이것이 벤치 마크가 제안하는 것입니다)

다른 팁

네, 당신은 당신의 설명이 있습니다.

3은 추가 메소드 호출로 인해 1보다 약간 느립니다.

2는 각 루프에서 '설정'및 '세분 다운'예외 관련 바이트 코드를 사용하지 않기 때문에 2보다 빠릅니다. 바이트 코드를 열면 Javap의 차이점을 확인할 수 있습니다. http://www.theserverside.com/tt/articles/article.tss?l=guidejavabytecode

2 또는 1을 사용하는지 여부는 동등하지 않기 때문에 원하는 동작에 따라 다릅니다. 나는 당신이 더 이상 사용되지 않은 방법을 사용하지 않기 때문에 3 이상의 3을 선택할 것입니다.이 방법은 작은 속도 증가보다 더 중요합니다. 그러나 그것이 일어나기 때문에 어쨌든 더 빠릅니다.

저를 수정하십시오. 그러나 Test2 For-Loop은 던지기 예외로 인해 1 단계 만 실행하고 Test1은 루프 내부의 예외를 발견하고 2500000 번 실행됩니다.

루프 밖에서 예외를 포착하면 루프가 다시 시작되지 않습니다. "int i"를 인쇄하여 루프가 몇 단계로 만들어 졌는지 확인하십시오.

세 번째는 가장 느리게 이루어집니다. 방법은 호출을 더 이상 사용되지 않은 메소드로 위임하기 때문입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top