Pergunta

Eu só escreveu uma sinopse toda sobre como cheguei a este ponto, mas percebi que é mais fácil de postar o código e deixar por isso mesmo:)

Tanto quanto eu posso dizer, o desempenho de test3 () deve ser o mesmo que test1 () - a única diferença é que a exceção é detectada (dentro do método pedindo test1 (), dentro do método chamado para test3 ())

Por que test3 () regularmente tomar algum tempo entre test1 () e test2 () para completar?

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");
    }

}

Running dá-me (JDK 1.6.0_13 no Windows XP) a saída:

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

Assim, as respostas são muito próximos (estamos falando de algo que é tão trivial que é irrelevante), btu Estou curioso!

Mais tarde ...

As pessoas têm sugerido que há otimização JVM ficar no caminho - Concordo. Então, eu quebrei cada teste para baixo em forma de si própria classe / principal e cada um individualmente. Os resultados deste:

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

observações interessantes:

  • A diferença entre pegar cada chamada contra pegando tudo fora do loop é reduzido em sua própria JVM (presumo otimização não vai o porco inteiro no caso all-tests-in-one devido aos outros iterações que foram realizado)
  • A diferença entre o try / catch do meu lado versus o try / catch dentro URLEncoder.encode () é agora muito menor (meio segundo mais 5.000.000 iterações), mas ainda consistantly lá ...
Foi útil?

Solução

Executá-lo na ordem que você postou:

Realizada 2500000 codificações tentando pegar cada um em 34208ms
Realizados 2500000 codificações tentando pegar todos em 31708ms
Realizada 2500000 codificações com um método obsoleto em 30738ms

Invertendo a ordem:

Interpretada 2500000 codificações com um Método Reprovado em 32598ms
Realizada 2500000 codificações tentando pegar todos em 31239ms
Realizada 2500000 codificações tentando pegar cada um em 31208ms

Portanto, eu realmente não acho que você está vendo o que você acha que você está vendo (certamente, test1 não é 66% mais lento do que test3, que é o que seus benchmarks sugerem)

Outras dicas

Sim, você tem a sua explicação, eu penso:

3 é ligeiramente mais lento do que 1 devido à chamada de método extra envolvido.

2 é mais rápido do que qualquer um desde que não 'set up' e 'derrubar' atraente exceção relacionada com bytecode em cada loop. Você pode se abrir o código de byte para ver a diferença com javap - veja http://www.theserverside.com/tt/articles/article.tss?l=GuideJavaBytecode

Se você usar 2 ou 1 depende de qual o comportamento que você quer, uma vez que eles não são equivalentes. Eu escolheria 1 sobre 3 desde que você então não está utilizando um método obsoleto, o que é mais importante do que pequenos aumentos de velocidade -. Mas como isso acontece 1 é mais rápido de qualquer maneira

Por favor me corrijam, mas TEST2 para-loop é executado apenas 1 passo, por causa da exceção de arremesso e test1 chamou a exceção dentro do loop e é executado 2500000 vezes.

Quando você capturar a exceção fora do loop, o loop não vai começar de novo. Imprimir "int i" para ter certeza de quantos passos do laço feito.

O terceiro é o mais lento, porque os delegados método a chamada para o método obsoleto.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top