Подтвердить что ты не робот

Нужно ли современному JavaScript JITers кэшировать длину массива в цикле?

Я нахожу, что практика кэширования свойства массива length внутри цикла for весьма неприятна. Как и в,

for (var i = 0, l = myArray.length; i < l; ++i) {
    // ...
}

В моих глазах, по крайней мере, это сильно ухудшает читаемость по сравнению с простым

for (var i = 0; i < myArray.length; ++i) {
    // ...
}

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

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

У кого-нибудь есть доказательства так или иначе?

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

4b9b3361

Ответ 1

Это зависит от нескольких вещей:

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

По показаниям, которые я видел (например, здесь и здесь), что производительность в IE < 9 (как правило, это самые медленные браузеры, с которыми вам приходится иметь дело) извлекает выгоду из кеширования длины массива, поэтому это может стоить того. Для чего это стоит, у меня давняя привычка кэшировать длину массива и, как результат, легко читать. Существуют также другие оптимизации циклов, которые могут иметь эффект, например, отсчет, а не вверх.

Вот соответствующее обсуждение этого из списка рассылки JSMentors: http://groups.google.com/group/jsmentors/browse_thread/thread/526c1ddeccfe90f0

Ответ 2

Мои тесты показывают, что все основные новые браузеры кэшируют свойство length массивов. Вам не нужно кэшировать его самостоятельно, если вы не обеспокоены IE6 или 7, я точно не помню. Тем не менее, с тех пор я использовал другой стиль итерации, поскольку он дает мне еще одно преимущество, которое я опишу в следующем примере:

var arr = ["Hello", "there", "sup"];
for (var i=0, str; str = arr[i]; i++) {
  // I already have the item being iterated in the loop as 'str'
  alert(str);
}

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

Ответ 3

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

var i = someArray.length;
while(i--){
    //doStuff to someArray[i]
}

Это не какая-то странная загадочная микро-оптимизация. Это просто основной принцип избегания работы. Не использовать '.' или '[]' более чем необходимо, должно быть столь же очевидным, как не пересчитывать pi более одного раза (предполагая, что вы не знали, что у нас уже есть это в объекте Math).

[rantish elements yoinked]

Если someArray полностью внутренне относится к функции, то это справедливая игра для оптимизации JIT своего свойства length, которая действительно похожа на getter, который на самом деле подсчитывает элементы массива каждый раз, когда вы обращаетесь к нему. JIT мог видеть, что он был полностью локализован и пропускал фактическое поведение подсчета.

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

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

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

Поиск кэширования свойств и возврат методов легко, очищает ваш код и в конечном итоге делает его более гибким и надежным с точки зрения производительности. Даже если один или два JIT сделали это ненужным в обстоятельствах, связанных с количеством "ifs", вы не могли быть уверены, что они всегда будут или ваш код будет продолжать делать это.

Итак, да, извинения за анти-let-the-compiler-handle-it rant, но я не понимаю, почему вы никогда не захотите не кэшировать свои свойства. Это легко. Он чист. Это гарантирует лучшую производительность независимо от браузера или перемещения объекта, имеющего свое свойство, рассмотренного во внешнюю область.

Но мне действительно кажется, что Word docs загружается так же медленно, как и в 1995 году, и что люди продолжают писать ужасно медленные Java-сайты, хотя Java VM якобы превосходит всех некомпилированных претендентов на производительность. Я думаю, что это понятие о том, что вы можете позволить компилятору разобраться в деталях производительности и что "современные компьютеры SO быстро" имеют много общего с этим. Мы всегда должны помнить об избегании работы, когда работу легко избежать и не угрожает удобочитаемости/ремонтопригодности, ИМО. Выполнение этого по-другому никогда не помогало мне (или я никому не подозреваю) быстрее писать код в долгосрочной перспективе.