2011-12-19 4 views
0

Я хочу, чтобы проверить время добавления и получения элемента в простом и родового HashMap:Неудачное время выполнения метода

public void TestHashGeneric(){ 


     Map hashsimple = new HashMap();    

     long startTime = System.currentTimeMillis(); 



     for (int i = 0; i < 100000; i++) { 
      hashsimple.put("key"+i, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); 
     } 

     for (int i = 0; i < 100000; i++) { 
      String ret =(String)hashsimple.get("key"+i); 
     } 
     long endTime =System.currentTimeMillis(); 

     System.out.println("Hash Time " + (endTime - startTime) + " millisec"); 

     Map<String,String> hm = new HashMap<String,String>(); 

     startTime = System.currentTimeMillis(); 



     for (int i = 0; i < 100000; i++) { 
      hm.put("key"+i, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); 
     } 

     for (int i = 0; i < 100000; i++) { 
      String ret = hm.get("key"+i); 
     } 
     endTime = System.currentTimeMillis(); 

     System.out.println("Hash generic Time " + (endTime - startTime) + " millisec");   

    } 

Проблема заключается в том, что я получаю другое время, если я поменять местами между кодом раздела HashMap в! Если я поставил петли (со сроком печати) общего числа ниже простого, я получаю лучшее время для родового, и если я стану простым ниже общего, я получаю лучшее время для простого!

То же самое происходит, если я использую для этого разные методы.

+0

Пожалуйста, отредактируйте свой вопрос, чтобы он приобрел больше смысла - на данный момент его очень трудно понять. Пожалуйста, прочитайте http://tinyurl.com/so-hints –

+0

Вопрос не ясен. Вы говорите, что у вас есть две якобы совершенно несвязанные части кода, а вторая, которая работает во втором, работает быстрее (наоборот, когда вы переключаете свой порядок)? Может быть JIT на работе, помимо всего прочего. Возможно, «разогрейте» обе части и выполните тайминги после этого. – Thilo

+1

Но я могу сказать вам следующее: дженерики оказывают нулевое влияние на производительность исполнения. Это чисто компиляция. – Thilo

ответ

0

Java Runtime довольно утонченно - он немного учится/оптимизируется во время работы. Возможно, вы сможете получить тест, который вы хотите, сначала разогрев JVM. Попробуйте позвонить TestHashGeneric() дважды и посмотреть, что дает второй набор результатов.

У вас также есть в два раза больше материала в памяти во время второго запуска. Есть всевозможные переменные, которые могут повлиять на этот тест.

1

JIT будет скомпилировать и оптимизировать вашу программу во время ее работы, поэтому второй запуск всегда будет быстрее.

Вы должны внести следующие изменения:

  1. Выполнить оба теста Untimed первый, а затем повторно запустить их по времени, так что вы не получите пострадавших от JIT.
  2. Вы должны использовать System.nanoTime(), так как это более точно для синхронизации (вы никогда не должны получать разницу 0).
  3. Вы также должны протестировать некоторые пустые методы, так как вы также синхронизируете операцию конкатенации строк в каждом цикле.

Также отметим, что в Java родовые типы стерты, так что не должно быть никакой разницы во время выполнения на всех.

+0

Да, конкатенация строк является одним из основных тестов. – kenny

0

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

1

Если у вас есть один цикл, который достигает порога компиляции (около 10K), весь метод компилируется. Это может сделать либо первый цикл более быстрым (так как он оптимизирован правильно, поскольку второй цикл не имеет информации о счетчике), либо второй цикл появляется после (когда он скомпилирован до его начала)

Этот простейший способ исправить это состоит в том, чтобы поместить каждый тест в свой собственный метод, и они будут скомпилированы и оптимизированы независимо. (Заказ все еще может иметь значение, но он менее важен). Я бы по-прежнему предлагал запустить тест несколько раз, чтобы увидеть, как результаты меняются.

Смежные вопросы