2010-10-20 2 views
0

я наткнулся через презентацию (dalvik-vm-internals) на Dalvik VM, в том, что он упоминается как для ниже петли, мы имеем использовать (2) и (3) и избегать (7).петли эффективность

(1) для (INT I = инициализатор; я> = 0; i--)

(2) предел INT предел = подсчет; для (int i = 0; i < limit; i ++)

(3) Тип [] array = get array; для (Тип OBJ: массив)

(4) для (INT I = 0; я < Array.length; я ++)

(5) для (INT I = 0; я < this.var; я ++)

(6) для (INT I = 0; я < obj.size(); я ++)

(7) Iterable список = получить список; для (Тип obj: список)

Комментарии: Я чувствую, что (1) и (2) одинаковы. (3) (4) каждый раз, когда ему приходится вычислять длину массива, поэтому этого можно избежать (5) (6) то же, что и (4), каждый раз рассчитывая размер (7) список имеет тип Iterable?

еще один, в случае, если мы имеем бесконечные данные (предположим, данные поступают в виде потока), какой цикл следует учитывать для повышения эффективности?)

запрос вы Прокомментируйте это ...

+0

Эта презентация с 2008 года, задолго до того, как компилятор JIT был представлен во Фройо. http://developer.android.com/guide/practices/design/performance.html#foreach новее, но я думаю, что этот документ также немного устарел. (Обновленная версия должна появиться на этом сайте, когда следующий выпуск исчезнет.) – fadden

+0

Спасибо за ссылку !! что было полезно – Vamsi

ответ

0

Если это то, что они рекомендуют, это то, что они оптимизировали для компилятора и виртуальной машины. Те, которые вы считаете одинаковыми, не обязательно реализуются одинаково: компилятор может использовать всевозможные трюки с анализом данных и путей, чтобы избежать наивно-дорогостоящих операций. Например, результат array.length() можно кэшировать, поскольку массивы неизменяемы.

Они ранжируются от большинства до наименее эффективных: но (1) является «неестественным». Я согласен, не так ли? Проблема с (7) заключается в том, что объект-итератор создается и должен быть GC'ed.

Примите во внимание внимательно, когда следует принять во внимание рекомендацию. Он явно предназначен для ограниченного числа итерации по известной коллекции, а не потока. Это имеет смысл только в том случае, если цикл оказывает значительное влияние на производительность и потребление энергии («работает на компьютерной шкале»). Первый закон оптимизации - «Не оптимизировать». Второй закон (для экспертов) - «Пока не оптимизировать». Сначала измерьте (время выполнения и потребление ЦП), оптимизируйте позже: это применимо даже к мобильным устройствам.

Вы должны учитывать предыдущие слайды: старайтесь спать так часто и как можно дольше, быстро реагируя на изменения. Как вы это делаете, зависит от того, с каким потоком вы имеете дело.

Наконец, обратите внимание, что презентация рассчитана на два года и может не полностью применяться к 2.2 устройства, в которых, среди прочего, реализован JIT.

+0

Да, я думаю, я упрощен !! но имеет ли он какую-либо разницу между (1) и (2) из-за пост-декремента и пост-приращения? – Vamsi

+0

См. Мою редакцию. Сравнение с произвольным целым обычно реализуется как вычитание и сравнение с нулем, поэтому (1) имеет очень незначительное преимущество в производительности по сравнению с (2), но требует от нас думать назад (и делает код менее удобным для обслуживания). Идите (1), только если вы ** знаете **, в этом коде есть узкое место производительности или процессорная точка процессора. И даже тогда ... –

+0

Спасибо! это было очень хорошее объяснение. – Vamsi

0

С бесконечными данными ни один из примеров не является достаточно хорошим. Лучше всего было бы сделать

for(;;) { 
    list.poll(); //handle concurrency, in java for example, use a blocking queue 
} 
+0

имеет ли это какое-либо значение, если мы используем ... while (1) {list.poll();}? – Vamsi

+0

Это не должно меняться, нет. – krico

0

1) и 2) действительно разные. 2) требуется дополнительное вычитание для вычисления i = 0. Еще лучше, на большинстве процессоров (и хорошо оптимизированный код) нет сравнения, необходимого для i> = 0. Процессор может использовать negative flag, что приводит к последнему декременту (i--).

Таким образом, конец цикла -1 выглядит (в псевдо-ассемблер)

--i 
jump-if-neg 

в то время как петля # 2

++i 
limit-i # set negative flag if i >limit 
jump-if-neg 

Это не делает большой разницы, за исключением случаев, кода в вашем цикле действительно мало (например, операция базовой строки C) Это может не работать с интерпретируемыми языками.

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