Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как оптимальнее - переменная внутри цикла или вне? 
V
    Опции темы
Entry_N3
  Дата 22.8.2008, 17:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 446
Регистрация: 8.2.2007

Репутация: нет
Всего: нет



Как оптимальнее - переменная внутри цикла или вне - и почему?

Вариант А.
Код

// на входе строковый массив a
for(int i=0; i<10; i++) {
     String item = a[i];
     ... // работа с item
}


Вариант Б.
Код

// на входе строковый массив a
String item;
for(int i=0; i<10; i++) {
     item = a[i];
     ... // работа с item
}


Т.е. вариант А или Б? Почему? Другие критерии?
PM MAIL   Вверх
SaSho
Дата 22.8.2008, 17:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 54
Регистрация: 10.6.2007
Где: Днепропетровск

Репутация: 2
Всего: 3



Насколько я понимаю, если нет надобности работать с объектом вне цикла, то оптимальнее использовать ссылку внутри цикла, дабы не держать лишнюю ссылку на последний объект массива...
P.S. А чем в приведенном выше примере не подходит вариант for-each? Или индекс i используется где-то ещё, кроме как для доступа к элементу массива?
PM MAIL ICQ Jabber   Вверх
Entry_N3
  Дата 22.8.2008, 17:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 446
Регистрация: 8.2.2007

Репутация: нет
Всего: нет



SaSho, твое мнение понял. Насчет for-each - речь не конкретно о массиве, а о переменных, которые как-то используются каждую итерацию цикла; вопрос в том, где их лучше объявлять.
PM MAIL   Вверх
SaSho
Дата 22.8.2008, 17:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 54
Регистрация: 10.6.2007
Где: Днепропетровск

Репутация: 2
Всего: 3



Блох в своём нетленном труде также рекомендует область видимости локальных переменных сводить к минимуму.
PM MAIL ICQ Jabber   Вверх
ivg
Дата 22.8.2008, 18:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Autonomous R&D
**


Профиль
Группа: Участник
Сообщений: 686
Регистрация: 8.2.2006
Где: Екатеринбург

Репутация: 33
Всего: 81



Цитата(Entry_N3 @  22.8.2008,  20:18 Найти цитируемый пост)
Как оптимальнее - переменная внутри цикла или вне - и почему?

С точки зрения производительности - одинаково. Смысл - ограничение области видимости переменной - но это уже заморочки компилятора и на производительность не влияют (Точнее не должны влиять).
PM MAIL   Вверх
dorogoyIV
Дата 22.8.2008, 18:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1503
Регистрация: 26.3.2007

Репутация: 3
Всего: 46



Цитата(Entry_N3 @  22.8.2008,  17:43 Найти цитируемый пост)
 вопрос в том, где их лучше объявлять.

имхо - удобнее вне цикла - всегда можно к ним обратиться (это если вдруг понадобится обратиться).
а в оптимизации разница будет не заметна человеческому глазу
PM MAIL   Вверх
ivg
Дата 22.8.2008, 20:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Autonomous R&D
**


Профиль
Группа: Участник
Сообщений: 686
Регистрация: 8.2.2006
Где: Екатеринбург

Репутация: 33
Всего: 81



Цитата(ivg @  22.8.2008,  21:02 Найти цитируемый пост)
С точки зрения производительности - одинаково.

Чтобы не быть голословным предлагаю сравнить байт-код двух методов:
Код

    public void a1(String[] a) {
     String s;
        for(int i = 0; i < 10 ; i++) {
            s = a[i];
        }
    }
    public void a2(String[] a) {
     for(int i = 0; i < 10 ; i++) {
            String s = a[i];
        }
    }
Код

 public void a1(java.lang.String[] a);
     0  iconst_0
     1  istore_3 [i]
     2  goto 12
     5  aload_1 [a]
     6  iload_3 [i]
     7  aaload
     8  astore_2 [s]
     9  iinc 3 1 [i]
    12  iload_3 [i]
    13  bipush 10
    15  if_icmplt 5
    18  return
      Local variable table:
        [pc: 0, pc: 19] local: this index: 0 type: test.Test
        [pc: 0, pc: 19] local: a index: 1 type: java.lang.String[]
        [pc: 9, pc: 12] local: s index: 2 type: java.lang.String
        [pc: 2, pc: 18] local: i index: 3 type: int
  
  public void a2(java.lang.String[] a);
     0  iconst_0
     1  istore_2 [i]
     2  goto 12
     5  aload_1 [a]
     6  iload_2 [i]
     7  aaload
     8  astore_3
     9  iinc 2 1 [i]
    12  iload_2 [i]
    13  bipush 10
    15  if_icmplt 5
    18  return
      Local variable table:
        [pc: 0, pc: 19] local: this index: 0 type: test.Test
        [pc: 0, pc: 19] local: a index: 1 type: java.lang.String[]
        [pc: 2, pc: 18] local: i index: 2 type: int
 Как видите байт-код аналогичен, различаются только индексы локальных переменных. Компилятор Eclipse 3.3;
PM MAIL   Вверх
maxim1000
Дата 23.8.2008, 10:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: нет
Всего: 110



Цитата(ivg @  22.8.2008,  18:02 Найти цитируемый пост)
Смысл - ограничение области видимости переменной - но это уже заморочки компилятора


ИМХО, всё-таки разница не только для компилятора:
переменная должна быть видна там, где предполагается её использование
если оно шире, после цикла станет видно на одну переменную больше, причём по задумке она там использоваться не должна, т.е. будет бесполезна
вот и получим, что ненужная сущность будет занимать место в "кеше" памяти программиста, отвлекая его от нужных вещей
а при программировании сложных систем, количество объектов, которые нужно держать в "кеше" критично

Цитата(dorogoyIV @  22.8.2008,  18:08 Найти цитируемый пост)
имхо - удобнее вне цикла - всегда можно к ним обратиться (это если вдруг понадобится обратиться).
а в оптимизации разница будет не заметна человеческому глазу 

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


--------------------
qqq
PM WWW   Вверх
dorogoyIV
Дата 23.8.2008, 11:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1503
Регистрация: 26.3.2007

Репутация: 3
Всего: 46



maxim1000, это все понятно.
конечно надо смотреть на логику самой проги.
по кусочку метода трудно что то сказать.
поэтому, Entry_N3, на ваше усмотрение...
PM MAIL   Вверх
Entry_N3
  Дата 23.8.2008, 17:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 446
Регистрация: 8.2.2007

Репутация: нет
Всего: нет



Спасибо за столь широкий взгляд. Лично я думал, что с точки зрения памяти, лучше вне цикла, чтобы не инстанцировать новый объект каждый раз при итерации по циклу, а оказалось, что, наоборот, после цикла переменная остается в памяти.
PM MAIL   Вверх
dorogoyIV
Дата 23.8.2008, 20:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1503
Регистрация: 26.3.2007

Репутация: 3
Всего: 46



Цитата(Entry_N3 @  23.8.2008,  17:51 Найти цитируемый пост)
Спасибо за столь широкий взгляд. Лично я думал, что с точки зрения памяти, лучше вне цикла, чтобы не инстанцировать новый объект каждый раз при итерации по циклу, а оказалось, что, наоборот, после цикла переменная остается в памяти.


кажется здесь ты ошибаешься - в цикле каждая переменная будет вешаться в память.
только джававский gc будет их удалять.
ну и ты можешь вызывать gc если нужно...
PM MAIL   Вверх
Entry_N3
  Дата 23.8.2008, 20:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 446
Регистрация: 8.2.2007

Репутация: нет
Всего: нет



dorogoyIV, ну так как лучше с точки зрения памяти - вне цикла или внутри? 
PM MAIL   Вверх
niasilil
Дата 23.8.2008, 21:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 325
Регистрация: 4.6.2007
Где: USA

Репутация: 8
Всего: 9



кстати, сколько байт в памяти занимает одна reference? чего то нигде не встречал. 

Это все ловля блох, примерно как табу на использование String внутри цикла - все говорят что "нельзя и все, надо StringBuilder/StringBUffer". При том что если цикл в 10 шагов, то GC все равно соберет эти String объекты и освободит память. 


--------------------
SCJP 5.0, SCJD
PM MAIL   Вверх
ivg
Дата 23.8.2008, 22:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Autonomous R&D
**


Профиль
Группа: Участник
Сообщений: 686
Регистрация: 8.2.2006
Где: Екатеринбург

Репутация: 33
Всего: 81



Цитата(dorogoyIV @  23.8.2008,  23:20 Найти цитируемый пост)
кажется здесь ты ошибаешься - в цикле каждая переменная будет вешаться в память

Если вы имеете ввиду, что для локальной переменной объявленной внутри цикла, при каждом проходе, будет выделяться новая ячейка памяти, то это не так. Будет использована старая. Вот тут - VM Spec: 3.6 Frames, можно посмотреть. И GC не управляет фрэймами локальных переменных, фрэйм создаётся/уничтожается при входе/выходе в/из метода.
Цитата(Entry_N3 @  23.8.2008,  23:45 Найти цитируемый пост)
ну так как лучше с точки зрения памяти - вне цикла или внутри? 

Внутри. После выхода за пределы блока, ячейка фрэйма может быть переиспользована компилятором для хранения другой локальной переменной. Следовательно меньше размер фрэйма локальных переменных, выделяемых методу.
Цитата(niasilil @  24.8.2008,  00:09 Найти цитируемый пост)
Это все ловля блох, примерно как табу на использование String внутри цикла - все говорят что "нельзя и все, надо StringBuilder/StringBUffer". При том что если цикл в 10 шагов, то GC все равно соберет эти String объекты и освободит память.

Почему табу? На это есть объективные причины. Например такой код:
Код

    public void call(String[] a) {
        String s = "";
        for (int i = 0; i < 10; i++) {
            s = s + a[i];
        }
    }
 компилятор преобразует примерно в такой:
Код

    public void call(String[] a) {
        String s = "";
        for (int i = 0; i < 10; i++) {
            s = (new StringBuilder(String.valueOf(s))).append(a[i]).toString();
        }
    }
 ,а мы напишем такой:
Код

    public void call(String[] a) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 10; i++) {
            sb.append(a[i]);
        }
        String s = sb.toString();
    }
 Легко догадаться, что наш вариант будет оптимальнее по производительности. smile 
PM MAIL   Вверх
Entry_N3
  Дата 23.8.2008, 22:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 446
Регистрация: 8.2.2007

Репутация: нет
Всего: нет



ivg, круто  smile 
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1830 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.