Который компилирует в более быстрый код: “n * 3” или “n + (n*2)”?

Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException вообще.

См. также: A хороший список лучших практик

Я бы добавил, очень важно, хорошо использовать модификатор final. Использование "окончательной" модификатор, когда это применимо в Java

Сводка:

  1. Используйте модификатор final для обеспечения хорошей инициализации.
  2. Избегайте возврата null в методы, например, при возврате пустых коллекций.
  3. Использовать аннотации @NotNull и @Nullable
  4. Быстрое завершение работы и использование утверждений, чтобы избежать распространения нулевых объектов через все приложение, когда они не должен быть пустым.
  5. Сначала используйте значения с известным объектом: if("knownObject".equals(unknownObject)
  6. Предпочитают valueOf() поверх toString ().
  7. Используйте null safe StringUtils StringUtils.isEmpty(null).

6
задан Bruce Alderman 20 November 2008 в 00:12
поделиться

11 ответов

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

55
ответ дан 8 December 2019 в 02:00
поделиться

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

Вы не должны пытаться предположить, 'быстрее' ли вещи, не проводя измерения.

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

4
ответ дан 8 December 2019 в 02:00
поделиться

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

MUL EAX,3

выполняется быстрее, чем

MOV EBX,EAX
SHL EAX,1
ADD EAX,EBX

Последний процессор, где этот вид оптимизации, возможно, был полезен, был, вероятно, 486. (да, это смещается к процессорам Intel, но вероятно представительное для другой архитектуры также).

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

15
ответ дан 8 December 2019 в 02:00
поделиться

Поскольку легко измерить его самостоятельно, почему не делают этого? (Используя gcc и time от cygwin)

/* test1.c */
int main()
{
    int result = 0;
    int times = 1000000000;
    while (--times)
        result = result * 3;
    return result;
}

machine:~$ gcc -O2 test1.c -o test1
machine:~$ time ./test1.exe

real    0m0.673s
user    0m0.608s
sys     0m0.000s

Сделайте тест для пару раз и повторитесь для другого случая.

Если Вы хотите посмотреть на ассемблерный код, gcc -S -O2 test1.c

10
ответ дан 8 December 2019 в 02:00
поделиться

Это действительно зависит от компилятора, который Вы на самом деле используете, но очень вероятно, они переводят в тот же код.

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

1
ответ дан 8 December 2019 в 02:00
поделиться

Не трудно узнать то, что компилятор делает с Вашим кодом (я использую DevStudio 2005 здесь). Запишите простую программу со следующим кодом:

int i = 45, j, k;
j = i * 3;
k = i + (i * 2);

Поместите точку останова в среднюю строку и выполните код с помощью отладчика. Когда точка останова инициирована, щелкните правой кнопкой по исходному файлу, и выбор "Переходят К Дизассемблированию". У Вас теперь будет окно с кодом, который выполняет ЦП. Вы заметите в этом случае, что последние две строки производят точно те же инструкции, а именно, "lea eax, [ebx+ebx*2]" (не разрядное смещение и добавление в данном случае). На современном ЦП IA32, вероятно, более эффективно сделать прямой MUL, а не бит, смещающийся из-за pipelineing природы ЦП, который подвергается штрафу при использовании измененного значения слишком скоро.

Это демонстрирует, какой aku говорит о, а именно, компиляторы достаточно умны для выбора лучших инструкций для кода.

4
ответ дан 8 December 2019 в 02:00
поделиться

Большинство компиляторов достаточно умно для разложения целочисленного умножения на серию сдвигов разряда, и добавляет. Я не знаю о компиляторах Windows, но по крайней мере с gcc можно заставить это выкладывать ассемблер, и если Вы смотрите на это, можно, вероятно, видеть идентичный ассемблер для обоих способов записать это.

1
ответ дан 8 December 2019 в 02:00
поделиться

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

:-)

1
ответ дан 8 December 2019 в 02:00
поделиться

Пока Вы используете достойный оптимизирующий компилятор, просто пишете код, это легко для компилятора понять. Это помогает компилятору выполнить умные оптимизации.

Вы задающий этот вопрос указываете, что оптимизирующий компилятор знает больше об оптимизации, чем Вы. Так доверяйте компилятору. Использовать n * 3.

Взгляните на этот ответ также.

1
ответ дан 8 December 2019 в 02:00
поделиться

Компиляторы способны оптимизировать код такой как Ваш. Любой современный компилятор произвел бы тот же код для обоих случаев и дополнительно заменил бы * 2 сдвигом влево.

0
ответ дан 8 December 2019 в 02:00
поделиться

Доверяйте своему компилятору для оптимизации маленьких кусочков кода как этот. Удобочитаемость намного более важна на уровне кода. Истинная оптимизация должна произойти в более высокий уровень.

0
ответ дан 8 December 2019 в 02:00
поделиться
Другие вопросы по тегам:

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