Исключения в цикле Java и устаревание (или это вещь URLEncoding?) - PullRequest
0 голосов
/ 25 мая 2009

Я только что написал целую рекламу о том, как я достиг этой точки, но решил, что легче опубликовать код и оставить его на этом:)

Насколько я могу судить, производительность test3 () должна быть такой же, как test1 () - единственное отличие состоит в том, где происходит исключение (внутри вызывающего метода для test1 (), внутри вызываемого метода для test3). ())

Почему 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

Итак, ответы довольно близки (мы говорим о чем-то, что настолько тривиально, что это неактуально), но мне любопытно!

Позже ...

Люди предположили, что мешает оптимизация JVM - я согласен. Итак, я разбил каждый тест на отдельный метод класса / main и каждый в отдельности. Результаты от этого:

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 (я полагаю, что оптимизация не идет полным ходом в случае всех тестов в одном из-за других итераций, выполняется)
  • Разрыв между try / catch на моей стороне и try / catch внутри URLEncoder.encode () теперь намного меньше (полсекунды за 5000000 итераций), но все же есть ...

Ответы [ 3 ]

1 голос
/ 25 мая 2009

Запуск в порядке, указанном вами:

Выполнено 2500000 кодировок при попытке поймать каждого в 34208ms
Выполнил 2500000 кодировок, пытаясь поймать все в 31708 мс
выполнено 2500000 кодировок с устаревшим методом в 30738мс

В обратном порядке:

Выполнено 2500000 кодировок с устарел метод в 32598мс
Выполнено 2500000 кодировок пытаюсь поймать все в 31239мс
выполнено 2500000 кодировок пытаясь поймать каждого в 31208ms

Поэтому я на самом деле не думаю, что вы видите то, что, по вашему мнению, видите (конечно, test1 не на 66% медленнее, чем test3, что и предлагают ваши тесты)

0 голосов
/ 25 мая 2009

Пожалуйста, исправьте меня, но цикл test2 for выполняет только 1 шаг, поскольку исключение броска и test1 перехватили исключение внутри цикла и выполняются 2500000 раз.

Когда вы перехватываете исключение за пределами цикла, цикл не запускается снова. Распечатайте «int i», чтобы узнать, сколько шагов сделал цикл.

Третий - самый медленный, поскольку метод делегирует вызов устаревшего метода.

0 голосов
/ 25 мая 2009

Да, у вас есть объяснение, я думаю:

3 немного медленнее, чем 1 из-за дополнительного вызова метода.

2 быстрее любого из них, поскольку он не «устанавливает» и «разбирает» связанный с перехватом байт-код в каждом цикле. Вы можете взломать байт-код, чтобы увидеть разницу с javap - см. http://www.theserverside.com/tt/articles/article.tss?l=GuideJavaBytecode

Если вы используете 2 или 1, зависит от того, какое поведение вы хотите, так как они не эквивалентны. Я бы выбрал 1 из 3, так как тогда вы не используете устаревший метод, который важнее, чем незначительное увеличение скорости, но, как это бывает, 1 все равно быстрее.

...