Циклы действительно быстрее наоборот? - PullRequest
252 голосов
/ 27 августа 2009

Я слышал это довольно много раз. Действительно ли циклы JavaScript действительно быстрее при обратном отсчете? Если так, то почему? Я видел несколько примеров набора тестов, показывающих, что обратные циклы быстрее, но я не могу найти объяснения, почему!

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

т.е.

for (var i = count - 1; i >= 0; i--)
{
  // count is only evaluated once and then the comparison is always on 0.
}

Ответы [ 34 ]

3 голосов
/ 31 октября 2012

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

Люди, которые говорят об использовании -- (или ++) для эффективного использования инструкций по сборке, не правы. Эти инструкции применяются к целочисленной арифметике, и в JavaScript нет целых чисел, только числа .

Вы должны написать читабельный код.

3 голосов
/ 31 октября 2012

Очень простыми словами

"i-- и i ++. На самом деле, они оба занимают одно и то же время".

но в этом случае, когда у вас есть инкрементная операция .. процессор оценивает .length каждый раз, когда переменная увеличивается на 1, а в случае уменьшения .. особенно в этом случае, он будет оценивать .length только один раз, пока мы не получим 0.

3 голосов
/ 31 октября 2012

Во-первых, i++ и i-- занимают одинаковое время на любом языке программирования, включая JavaScript.

Следующий код занимает много разного времени.

Fast:

for (var i = 0, len = Things.length - 1; i <= len; i++) { Things[i] };

Slow:

for (var i = 0; i <= Things.length - 1; i++) { Things[i] };

Поэтому следующий код тоже занимает другое время.

Fast:

for (var i = Things.length - 1; i >= 0; i--) { Things[i] };

Slow:

for (var i = 0; i <= Things.length - 1; i++) { Things[i] };

P.S. Медленно медленно только для нескольких языков (механизмы JavaScript) из-за оптимизации компилятора. Лучше всего использовать '<' вместо '<=' </strong> (или '=') и '- i' вместо 'i -' .

3 голосов
/ 31 октября 2012

Не так много времени уходит на i-- или i ++. Если вы углубитесь в архитектуру процессора, ++ будет более быстрым, чем --, так как операция -- сделает дополнение 2, но это произойдет внутри аппаратного обеспечения, так что это сделает его быстрым и не будет существенной разницы между ++ и -- также эти операции считаются наименьшими затратами времени в CPU.

для цикла работает следующим образом:

  • Инициализируйте переменную один раз в начале.
  • Проверьте ограничение во втором операнде цикла, <, >, <= и т. Д.
  • Затем примените цикл.
  • Увеличивайте цикл и снова запускайте эти процессы.

Итак,

for (var i = Things.length - 1; i >= 0; i--) {
    Things[i]
}; 

вычислит длину массива только один раз в начале, и это не так много времени, но

for(var i = array.length; i--; ) 

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

3 голосов
/ 08 октября 2009

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

Это потому, что только несколько движков Javascript (те, что в списке JIT) фактически генерируют код машинного языка.

Большинство движков Javascript создают внутреннее представление исходного кода, которое они затем интерпретируют (чтобы получить представление о том, на что это похоже, посмотрите в нижней части этой страницы на SpiderMonkey в Firefox). Обычно, если фрагмент кода делает практически то же самое, но приводит к более простому внутреннему представлению, он будет работать быстрее.

Имейте в виду, что при таких простых задачах, как сложение / вычитание единицы из переменной или сравнение переменной с чем-либо, издержки интерпретатора при переходе от одной внутренней «инструкции» к следующей довольно высоки, поэтому меньше «инструкций» ", которые используются внутренним движком JS, тем лучше.

3 голосов
/ 30 октября 2012

Он использовал , чтобы сказать, что --i был быстрее (в C ++), потому что есть только один результат, уменьшенное значение. i-- необходимо сохранить уменьшенное значение обратно в i, а также сохранить исходное значение в качестве результата (j = i--;). В большинстве компиляторов это использовало два регистра, а не один, что могло привести к тому, что другая переменная должна быть записана в память, а не сохранена как переменная регистра.

Я согласен с теми, кто сказал, что в наши дни нет никакой разницы.

1 голос
/ 27 августа 2009

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

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

1 голос
/ 31 октября 2012

Не будет ли компилятор кэшировать .length, и, следовательно, не имеет значения, сравниваете ли вы 0 или .length? Я предполагаю, что это очень специфично для компилятора или интерпретатора, с которым вы имеете дело.

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

1 голос
/ 27 августа 2009

Мне нравится, много оценок, но нет ответа: D

Проще говоря, сравнение с нулем всегда самое быстрое сравнение

Так что (a == 0) на самом деле быстрее возвращает True, чем (a == 5)

Он маленький и незначительный, и из 100 миллионов строк в коллекции его можно измерить.

Т.е. в цикле вы можете сказать, где i <= array.length и увеличивать i </p>

в нисходящем цикле вы можете говорить, где i> = 0, и вместо этого уменьшать i.

Сравнение происходит быстрее. Не «направление» цикла.

1 голос
/ 17 августа 2012

ПОМОГИТЕ ДРУГИМ, ЧТОБЫ ИЗБЕГАТЬ ГОЛОВНОЙ БОРЬБЫ --- ГОЛОСОВАТЬ ЭТО !!!

Самый популярный ответ на этой странице не работает для Firefox 14 и не проходит через jsLinter. Для циклов while требуется оператор сравнения, а не присваивание. Это работает на хром, сафари и даже т.е. Но умирает в Firefox.

ЭТО сломано!

var i = arr.length; //or 10
while(i--)
{
  //...
}

ЭТО БУДЕТ РАБОТАТЬ! (работает на firefox, передает jsLinter)

var i = arr.length; //or 10
while(i>-1)
{
  //...
  i = i - 1;
}
...