2016-09-26 3 views
2

Я пытался измерить производительность моего пользовательского итератора над простым массивом int. Это действительно просто, как показано ниже:Пользовательский Iterator медленный

class IntArrayIterator_NoCheck implements Iterator<Integer> { 

    private final int[] array; 
    private int counter = 0; 

    public IntArrayIterator_NoCheck(int[] array) { 
     this.array = array; 
    } 

    @Override 
    public boolean hasNext() { 
     return counter < array.length; 
    } 

    @Override 
    public Integer next() { 
     return array[counter++]; 
    } 

} 

После сравнения с ArrayList итератора и находки (http://trove.starlight-systems.com/), я обнаружил странные результаты. Тестирование проводилось следующим образом:

  • Списка/массив 100000 случайных ИНТ элементов
  • разминочных
    • 10000x Итерация по всей коллекции
    • 10000x итерации по всей коллекции снова
  • Испытание
    • 10000x итерация по всей коллекции, измерение с помощью System.nanoTime И ThreadMXBean.getCurrentThreadCpuTime()

Итератор Trove TIntArrayList это самый быстрый один с 30 мс выполнения. Итератор Java ArrayList имел время выполнения 85 мс. Пользовательский итератор по простому массиву int имел время работы 320 мс!

Какова возможная причина для ужасного исполнения моего пользовательского итератора? После просмотра реализаций итераторов ArrayList и TIntArrayList они намного сложнее (выполняют больше операций), поэтому я не понимаю, почему это происходит быстрее. Может, кто-нибудь, пожалуйста, объясните мне это?

+0

Не записывайте такой код для сравнения, используйте JMH: http://openjdk.java.net/projects/code-tools/jmh/ – leventov

+0

Благодарим за предложение! Я посмотрю. –

ответ

4

Ваш метод next будет производить тот же байт-код, как

public Integer next() { 
    return Integer.valueOf(array[counter++]); 
} 

Обратите внимание, что для любого int вне диапазона кэшированных значений (только Гарантируется быть -128 в 127) новый объект Integer создается.

Это не происходит для ArrayList, так как преобразование происходит до хранения Integer s в списке.
TArrayList имеет a custom iterator type, который возвращает примитивный тип int, который не требует создания объекта Integer.

+0

Спасибо! Я этого не осознавал. –

3

У вас есть итератор Integer там, но вы используете массив Int.

Таким образом, вы выполняете постоянную распаковку при итерации. Вы знаете; превращение Integer в ints и обратно - дорогостоящая операция; и делает это для каждой итерации - убивает вас.

Как и каждый звонок в следующий означает бокс с int в Integer.

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