2014-01-12 7 views
1

Вопрос связан с памятью и основными характеристиками. Последние несколько дней я размышлял над этой темой, это не то, что мне нужно было использовать, просто любопытно. Я создал простой пример:Создание объектов и делегирование гораздо медленнее, чем один большой метод?

1) Один класс, который не использует делегирование и не имеет внутренних классов:

public class NoInnerClass { 
public void theMethod(int times){ 
    for(int i=0; i<times; i++){ 
     System.out.println("No Inner hello: " + i); 
    } 
} 
} 

2) Один класс, который вызывает четыре внутренних классов. Последний из них делает то же самое, как и в методе NoInnerClass theMethod

public class InnerMain { 
    private Inner1 inner1 = new Inner1(); 

    public void theMethod(int times){ 
     inner1.doIt(times); 
    } 
} 

...

public class Inner4 { 
public void theMethod(int times){ 
    for(int i=0; i<times; i++){ 
     System.out.println("Inner 4 hello: " + i); 
    } 
} 
} 

Я измерил разницу во времени в миллисекундах между этими двумя типами вызовов. Разница была не такой большой - чуть более одной миллисекунды. Но что, если у нас есть намного более сложные внутренние объекты и более делегирующие вызовы, мы наверняка имели бы большую разницу.

Так вопросы:

  • Будет ли разница во времени и объема памяти, используемой между двумя подходами значительно увеличить
  • Если да, то есть ли какие-нибудь статьи по этому поводу (я не мог найти много)
  • Или, может быть, сегодняшняя JVM настолько умный, что мы не должны думать об этом

заранее спасибо за ваши ответы.

+5

Это: «* Или, может быть, сегодняшняя JVM настолько умна, что мы не должны думать об этом». ... Очевидная оптимизация здесь будет методом inlining, который должен скомпилировать два кода по существу по тем же инструкциям .. Кстати, разница, которую вы обнаружите, может быть проблемой измерения, а не фактической разницей в производительности. – assylias

+0

Исправить ваш отступ –

+0

Разница - среднее число нескольких попыток. И спасибо за напоминание о встроенном коде :) – user3188414

ответ

5

Разница, которую вы находите (чуть более одной миллисекунды), может быть артефактом вашей техники бенчмаркинга. Более того, бессмысленно говорить о миллисекундах, не зная времени всего прогона: если время составляет сотни миллисекунд, то разница небольшая; если само время в миллисекундах с одной цифрой, разница значительна; если время в секундах, то разница представляет собой ошибку измерения.

Современные JVM оптимизировали виртуальные вызовы на такие уровни эффективности, что любая разница, которую вы могли видеть, было бы очень трудно измерить. Гораздо лучше сосредоточиться на том, чтобы сделать код максимально понятным, используя все доступные для вас методы кодирования, включая виртуальный вызов, и начать оптимизацию только тогда, когда ваш профилировщик говорит вам, что это необходимо.

+0

Спасибо, я согласен с вами во всем, что вы говорите. Код является лишь примером. Но что делать, если у нас есть большие объекты и больше делегирования ... – user3188414

+1

@ user3188414 Размер объектов не имеет значения. Более того, увеличение размера методов ваших объектов уменьшит долю накладных расходов. Если у вашей программы нет проблем с производительностью, оптимизация ее - пустая трата времени. Если у вашей программы есть проблемы с производительностью, это почти гарантия того, что накладные расходы на виртуальные вызовы не составят список топ-100, который замедлит вашу программу. – dasblinkenlight

+0

Это ответ, который я хотел услышать :) Спасибо. – user3188414

2

Разница будет незначительной для подавляющего большинства программ. Да, для вызова метода может потребоваться несколько десятков циклов процессора, но для большинства методов это намного меньше, чем метод invoked. В вашем случае вы делаете I/O. Даже если это просто консоль, перерисовка этой консоли будет намного дороже, чем вызов метода.

Кроме того, JVM отлично справляется с вызовами метода inline, что еще больше сокращает накладные расходы метода (оставляя только проверку типа для переопределяемого метода).

Я рекомендую не беспокоиться о производительности языковых конструкций до тех пор, пока у вас не появится фактическая проблема с производительностью в коде.

PS: миллисекунда для 4 вызовов метода не правдоподобна. Это, вероятно, артефакт вашего бенчмаркинга. (Насколько точным является таймер? Вы уверены, что эталонный поток не был призван дать CPU другой программе?Вы используете паузу для сбора мусора? Прошел ли простой компилятор времени?)

О, и о памяти: разница в 4 предметах в куче. Конечно, это зависит от того, что эти объекты (если каждый ссылается на огромный массив, это может иметь значение), но небольшие объекты занимают 16 байт памяти. Неужели вы можете сэкономить 4 * 16 = 64 байта памяти? Или вы спрашиваете о увеличенном размере стека? Это тоже незначительно.

+0

Спасибо всем за ваши комментарии. В этом разделе я хотел задать вопрос - это создание объектов и вызов метода намного медленнее, чем встроенный код. И код довольно прост, я написал его здесь, как пример. Главное - что, если у нас в реальном приложении больше объектов и больше делегирования ... – user3188414

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