Который стоит больше во время цикла;присваивание или оператор if? - PullRequest
17 голосов
/ 28 октября 2010

Рассмотрим следующие 2 сценария:

boolean b = false;
int i = 0;
while(i++ < 5) {
    b = true;
}

ИЛИ

boolean b = false;
int i = 0;
while(i++ < 5) {
    if(!b) {
        b = true;
    }
}

Что делать «дороже»?Если ответ зависит от используемого языка / компилятора, пожалуйста, предоставьте.Мой основной язык программирования - Java.

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

Ответы [ 6 ]

29 голосов
/ 28 октября 2010

Пожалуйста, не забывайте правила Клуба оптимизации .

  1. Первое правило Клуба оптимизации - вы не оптимизируете.
  2. Второе правилоКлуб оптимизации - вы не оптимизируете без измерения.
  3. Если ваше приложение работает быстрее, чем базовый транспортный протокол, оптимизация завершена.
  4. Один фактор за раз.
  5. Без маркетроидов, без рыночных расписаний.
  6. Тестирование будет продолжаться столько, сколько потребуется.
  7. Если это ваша первая ночь в Клубе оптимизации, вы должны написать тестовый пример,

Кажется, что вы нарушили правило 2. У вас нет измерения.Если вы действительно хотите знать, вы сами ответите на вопрос, настроив тест, который запускает сценарий A в сравнении со сценарием B и находит ответ.Между разными средами так много различий, что мы не можем ответить.

3 голосов
/ 28 октября 2010

Вы проверяли это?Работая в системе Linux, я поместил ваш первый пример в файл с именем LoopTestNoIf.java, а второй - в файл с именем LoopTestWithIf.java, обернул основную функцию и класс вокруг каждой из них, скомпилировал и затем запустил с помощью этого сценария bash:

#!/bin/bash
function run_test {
  iter=0
  while [ $iter -lt 100 ]
  do
    java $1
    let iter=iter+1
  done
}
time run_test LoopTestNoIf
time run_test LoopTestWithIf

Результаты были такими:

real    0m10.358s 
user    0m4.349s 
sys     0m1.159s 

real    0m10.339s
user    0m4.299s 
sys     0m1.178s

Показывает, что наличие if делает его немного быстрее в моей системе.

1 голос
/ 28 октября 2010

Пытаетесь ли вы выяснить, выполняется ли выполнение каждого цикла быстрее в общем времени выполнения, чем проверка каждого цикла и только назначение один раз при выполнении условия теста?

В приведенном выше примере я быУгадай, что первый быстрее.Вы выполняете 5 заданий.В последнем случае вы выполняете 5 тестов, а затем выполняете задание.

Но вам нужно увеличить счетчик итераций и добавить некоторые таймеры секундомера, чтобы точно знать.

0 голосов
/ 14 июля 2018

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

Чтобы убедиться, что ваш (мой) тест действителен, вы (I) должны сделать достаточно итераций, чтобы получить достаточно данных. Каждая итерация должна быть достаточно «длинной» (я имею в виду временную шкалу), чтобы показать истинную разницу. Я обнаружил, что даже одного миллиарда итераций недостаточно, чтобы соответствовать временному интервалу, который был бы достаточно длинным ... Поэтому я написал этот тест:

for (int k = 0; k < 1000; ++k)
{
    {
        long stopwatch = System.nanoTime();

        boolean b = false;
        int i = 0, j = 0;
        while (i++ < 1000000)
            while (j++ < 1000000)
            {
                int a = i * j; // to slow down a bit
                b = true;
                a /= 2; // to slow down a bit more
            }

        long time = System.nanoTime() - stopwatch;
        System.out.println("\\tasgn\t" + time);
    }
    {
        long stopwatch = System.nanoTime();

        boolean b = false;
        int i = 0, j = 0;
        while (i++ < 1000000)
            while (j++ < 1000000)
            {
                int a = i * j; // the same thing as above
                if (!b)
                {
                    b = true;
                }
                a /= 2;
            }

        long time = System.nanoTime() - stopwatch;
        System.out.println("\\tif\t" + time);
    }
}

Я запустил тест три раза, сохранив данные в Excel, затем поменял местами первый (asgn ’) и второй (and if’) случай и повторил его три раза снова… И результат? Четыре раза «выиграл» случай «если» и два раза «asgn» оказался лучшим. Это показывает, насколько чувствительным может быть выполнение. Но в целом я надеюсь, что это также доказало, что дело «если» является лучшим выбором.

Спасибо, в любом случае…

0 голосов
/ 28 октября 2010

Относительно вашего базового примера (и, возможно, вашего реального приложения):

boolean b = false;
// .. other stuff, might change b
int i = 0;
// .. other stuff, might change i
b |= i < 5;
while(i++ < 5) {
    // .. stuff with i, possibly stuff with b, but no assignment to b
}

проблема решена?

Но на самом деле - это будет вопрос стоимости вашего теста (как правило, больше, чем просто if (boolean)) и стоимость вашего задания (как правило, больше, чем просто primitive = x).Если тест / задание дорогое, или ваш цикл достаточно длинный, или у вас достаточно высокие требования к производительности, вы можете разбить его на две части - но все эти критерии требуют тестирования того, как все работает.Конечно, если ваши требования более требовательны (скажем, b может переключаться назад и вперед), вам может потребоваться более сложное решение.

0 голосов
/ 28 октября 2010

Любой компилятор (кроме, возможно, отладочного) оптимизирует оба эти оператора до

bool b = true;

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

...