0

Я просто написали целую аннотацию о том, как я дошел до этого места, но поняли, что легче разместить код и оставить его в этом :)Java Исключения Loops и устаревание (или это URLEncoding вещь?)

As насколько я могу судить, производительность 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 мешая - я согласен. Итак, я разбил каждый тест на свой собственный класс/основной метод и каждый отдельно. Результаты этого:

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 

Интересные наблюдения:

  • Зазор между ловя каждый вызов против ловли все вне цикла уменьшается в его собственной виртуальной машины Java (я предполагаю, что оптимизация не будет на всю катушку в случае «все тесты в одном» из-за других выполненных итераций)
  • Разрыв между попыткой/захватом на моей стороне и попыткой/захватом внутри URLEncoder.encode() теперь намного меньше (половина второй более 5000000 итераций), но все еще постоянно там ...
+0

Пробуйте испытания в другом порядке: test2(), test3(), test1(), чтобы изолировать любые различия из-за компиляции JIT. – erickson

ответ

1

Запуск его в порядке, публикуемую:

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

Снятие и установка заказа:

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

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

+0

Хм ... Я выработал каждый тест в своем собственном основном классе, поэтому не может быть никакой оптимизации между мерами, мешающими мне, я вижу: 1 - Выполнено 2500000 кодировок, пытающихся поймать каждый в 5016 мс 1 - Выполняемая 5000000 кодировки, пытаясь поймать каждый в 7547ms 2 - Выполняемые 2500000 кодировки пытается поймать все в 4719ms 2 - Выполняемые 5000000 кодировки пытается поймать все в 7250ms 3 - Выполняемые 2500000 кодирования с устаревшим методом в 5297ms 3 - Выполнено 5000000 кодировок с устаревшим методом в 8015ms Устаревший тест все еще немного медленнее. Опять же, только в меру! :/ – Martin

+0

Бла - комментарий был прикручен к форматированию ...См. Исходный текст для обновления – Martin

0

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

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

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

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

0

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

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

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

+1

Исключение никогда не бросается - кодировка действительна для всех из них - это скорее вопрос «что делает JVM в случае его броска» (распечатка чего-то в каждом цикле проверяет это) – Martin

+0

спасибо Мартину, хотя бы исключение было брошено. –