Какой цикл имеет лучшую производительность? Почему?

Я использую DTO.

Мне не нравятся недостатки, но кажется, что другие варианты еще хуже:

Экспозиция объектов домена может привести к проблемам безопасности и утечки данных. Аннотации Джексона, похоже, могут решить проблему, но слишком легко совершить ошибку и выставить данные, которые не следует раскрывать. При разработке класса DTO гораздо сложнее сделать такую ​​ошибку.

С другой стороны, недостатки подхода DTO могут быть уменьшены с помощью таких объектов, как сопоставление объектов с объектами, и Lombok для меньше плитки.

50
задан 7 revs, 6 users 64% 13 April 2009 в 09:24
поделиться

7 ответов

Ограниченный объем Лучший

Использование Ваша вторая опция:

for ( ... ) {
  String s = ...;
}

Объем не Влияет на Производительность

, Если Вы демонтируете, кодируют скомпилированный от каждого (с JDK javap инструмент), Вы будете видеть, что цикл компилирует в те же самые инструкции по JVM в обоих случаях. Обратите внимание также, что Brian R. Bondy "Опция № 3" идентична Опции № 1. Ничто дополнительное не добавлено или удалено из стека при использовании более трудного объема, и те же данные используются на стеке в обоих случаях.

Избегают Преждевременной Инициализации

, единственная разница между этими двумя случаями - то, что в первом примере переменная s излишне инициализируется. Это - отдельный вопрос от местоположения объявления переменной. Это добавляет две потраченных впустую инструкции (чтобы загрузить строковую константу и сохранить ее в слоте стекового фрейма). Хороший инструмент статического анализа предупредит Вас, что Вы никогда не читаете значение, которое Вы присваиваете s, и хороший JIT-компилятор будет, вероятно, игнорировать его во времени выполнения.

Вы могли зафиксировать это просто при помощи пустого объявления (т.е. String s;), но это считают плохой практикой и имеет другой побочный эффект, обсужденный ниже.

Часто поддельное значение как null присвоено переменной просто для успокаивания ошибки компилятора, что переменная читается без того, чтобы быть инициализированным. Эта ошибка может быть взята в качестве подсказки, что переменный объем является слишком большим, и что это объявляется, прежде чем будет необходимо получить допустимое значение. Пустые объявления вынуждают Вас рассмотреть каждый путь выполнения кода; не игнорируйте это ценное предупреждение путем присвоения поддельного значения.

Сохраняют Слоты Стека

, Как упомянуто, в то время как инструкции по JVM являются тем же в обоих случаях, существует тонкий побочный эффект, который делает его лучше всего, на уровне JVM, для использования возможного наиболее ограниченного объема. Это видимо в "таблице локальных переменных" для метода. Рассмотрите то, что происходит, если у Вас есть несколько циклов с переменными, объявленными в излишне большом объеме:

void x(String[] strings, Integer[] integers) {
  String s;
  for (int i = 0; i < strings.length; ++i) {
    s = strings[0];
    ...
  }
  Integer n;
  for (int i = 0; i < integers.length; ++i) {
    n = integers[i];
    ...
  }
}

переменные s и n могли быть объявлены в их соответствующих циклах, но так как они не, компилятор использует два "слота" в стековом фрейме. Если они были объявлены в цикле, компилятор может снова использовать тот же слот, делая стековый фрейм меньшим.

, Что Действительно Вопросы

Однако большинство этих проблем является несущественным. Хороший JIT-компилятор будет видеть, что не возможно считать начальное значение, которое Вы расточительно присваиваете и оптимизируете присвоение далеко. Сохранение слота здесь или там не собирается решать судьбу Вашего приложения.

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

108
ответ дан Community 7 November 2019 в 10:31
поделиться

В теория , это - трата ресурсов для объявления строки в цикле. В практика , однако, оба из отрывков, которые Вы представили, скомпилируют вниз в тот же код (объявление вне цикла).

Так, если Ваш компилятор делает какой-либо объем оптимизации, нет никакого различия.

22
ответ дан Esteban Araya 7 November 2019 в 10:31
поделиться

В целом я выбрал бы второй, потому что объем' переменной ограничен циклом. Преимущества:

  • Это лучше для программиста, потому что Вы не должны волноваться о' том, чтобы быть используемым снова где-нибудь позже в функции
  • , Это лучше для компилятора, потому что объем переменной меньше, и таким образом, это может потенциально сделать больше анализа и оптимизации
  • , Это лучше для будущих читателей, потому что они не зададутся вопросом, почему' переменная объявляется вне цикла, если это никогда не использовало позже
17
ответ дан Greg Hewgill 7 November 2019 в 10:31
поделиться

Если Вы хотите убыстриться для циклов, я предпочитаю объявлять макс. переменную рядом со счетчиком так, чтобы никакие повторные поиски для condidtion не были необходимы:

вместо

for (int i = 0; i < array.length; i++) {
  Object next = array[i];
}

я предпочитаю

for (int i = 0, max = array.lenth; i < max; i++) {
  Object next = array[i];
}

Любые другие вещи, которые нужно рассмотреть, были уже упомянуты, поэтому просто мои два цента (см. сообщение ericksons)

Greetz, GHad

6
ответ дан GHad 7 November 2019 в 10:31
поделиться

Для прибавления по немного к ответ Esteban Araya они оба потребуют создания новой строки каждый раз через цикл (как возвращаемое значение some Assignment выражение). Те строки должны быть собраны "мусор" так или иначе.

4
ответ дан Community 7 November 2019 в 10:31
поделиться

Мне кажется, что нам нужно больше спецификации проблемы.

s = some Assignment;

не определяется относительно того, какое присвоение это. Если присвоение

s = "" + i + "";

тогда должно быть выделено, новое жало.

, но если бы это

s = some Constant;

, только с укажет на ячейку памяти констант, и таким образом первая версия была бы большей эффективной памятью.

Кажется мной мало глупый волноваться собирающийся много оптимизации для цикла для интерпретируемого Ленга, по моему скромному мнению.

1
ответ дан Milhous 7 November 2019 в 10:31
поделиться

Нижний регистр верблюда рекомендуется для полей и параметры.

Пример 1 :

fileName // for fields, parameters, etc.
FileName // for properties, class names, etc.

Обычно используется fileName , а НЕ filename ; Вы можете убедиться в этом, прочитав исходный код материалов с открытым исходным кодом, созданных Microsoft, таких как Enterprise Library .

Причины :

  1. Основным пунктом является что имена в этом случае более читабельны.
  2. Также этот подход добавляет согласованность , когда несколько параметров (полей, переменных ..) используются в одном и том же методе (классе ..) и с тем же префиксом " атаки с использованием сценариев, ключевые вирусы, кража личных данных и бот-сети (машины, которые были захвачены за преступную деятельность).

    Хорошо задокументировано, что IE6 менее безопасен, чем современные браузеры при серфинге в Интернете:

    « ... самая веская причина для обновления - улучшенная безопасность. Интернет сегодня - это не Интернет пятилетней давности. Есть опасности, которых просто не было в 2001 году, когда Internet Explorer 6 был выпущен для всего мира ». Сэнди Хардмайер, Microsoft MVP

    «Старые браузеры - это швейцарская дыра в безопасности, которая позволяет черным шляпам захватывать компьютеры, создавать бот-сети и даже красть личность жертвы, большую часть времени без их ведома. «. www.joelevi.com

    IE 6 представляет угрозу безопасности для любого компьютера, на котором он используется для просмотра веб-страниц. Любая ответственная ИТ-команда обновится до IE7 или более поздней версии на всех компьютерах в корпоративной сети. Многие теперь устанавливают браузер Firefox для дальнейшего повышения безопасности.

    Он не соответствует стандартам

    IE 6 не отображает веб-страницы так же, как большинство браузеров, так как использует собственный механизм, который игнорирует многие из стандарты, установленные W3C (Консорциум World Wide Web). Это приводит к тому, что некоторые веб-страницы отображаются некорректно в IE 6, а некоторые вообще не отображаются.

    Это также означает, что в то время как веб-разработчикам приходится поддерживать IE 6, большая часть их работы занимает исправление страниц, а не разработка лучшего контента. и особенности. Короче говоря, IE 6 сдерживает развитие Интернета для всех пользователей.

    Медленнее

    В течение последних 8 лет разработки браузеров, а также улучшения безопасности браузеры были настроены для повышения производительности на всех фронтах, включая скорость загрузки, скорость рендеринга и производительность JavaScript / AJAX, которая является технологией, используемой на большинстве крупных сайтов. для лучшего взаимодействия с конечным пользователем (иногда его называют технологией Web 2.0).

    Использование памяти

    Internet Explorer 7 фактически использует меньше памяти, чем IE6, и использует меньше общих ресурсов на машине. Таким образом, обновление может повысить производительность старых компьютеров.

    Обновление до Firefox или Chrome

    Firefox

    http://en-us.www.mozilla.com/en-US/firefox/firefox.html

    Chrome

    http://www.google.co.uk/chrome

    Обновление до IE 7/8

    Домашние пользователи

    Internet Explorer 7 http://www.microsoft.com /downloads/details.aspx?displaylang=en& Я добавил немного, что немного связано.

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

    В этом случае «v1» и «v2», по-видимому, не нужны и могут быть исключены для упрощения кода, но были добавлены для повышения производительности.

    public boolean contentEquals(StringBuffer sb) {
        synchronized(sb) {
            if (count != sb.length())
                return false;
            char v1[] = value;
            char v2[] = sb.getValue();
            int i = offset;
            int j = 0;
            int n = count;
            while (n-- != 0) {
                if (v1[i++] != v2[j++])
                    return false;
            }
        }
        return true;
    }
    
3
ответ дан 7 November 2019 в 10:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: