Pull to refresh

Comments 33

хэши лучше проверять так: hash[ name ] === 1
иначе можно напороться на одно из полей, унаследованных из глобального прототипа.
>Если же нам нужно проверить просто существование переменных и их неотрицательность.
Несуществующая переменная конечно же не сможет выбросить ошибку в вашем славном примере.

>Здесь мы используем сравнение без приведения типов ===, которое в случае нечисловых переменных работает быстрее обычного сравнения на 10–20%.
Типы в примере совпадают, конвертации значений нет, в этом случае что строгое, что нестрогое сравнение работает одинаково. При разных типах строгое сравнение тут же выкинет false, чего тут скорость сравнивать-то.

>Такая конструкция отработает на 40% быстрее, чем аналогичный exec
test — эквивалент RegExp.prototype.exec(string) != null, ой, не верю в 40%… В целом, итоговой таблице сильно не хватает столбца со ссылками на тесты в разных движках, чтоб своими глазами увидеть эти 10-20-30-40-50 процентов… ;)

.test не запоминает найденные подстроки в круглых скобках (переменные RexExp.$1..n), отсюда и экономия, тоже самое в .match
К тому же вообще не запоминает найденную строку.
Для ускорения регулярок можно «не запоминающие скобки» делать /(?:\d|-)*/ вместо «запоминающих» /(\d|-)*/
Это лишь пример, понятно что регулярка глупая.

Судя по всему .match любые скобки не запоминяет в отличии от .exec? что объясняет разницу производительности.
При работе 'test' свойства у RegExp, и у RegExp instance создаются/обновляются также, как и при работе 'exec', вспомните часто встречающуюся ошибку «test работает через раз», где речь идёт об обновляемом свойстве 'lastIndex'. Это касается и RegExp.$n и проч.

Проигрыш в производительности 'exec' связан скорее всего с необходимостью при нахождении совпадений вернуть определённый массив плюс заодно обвешать его свойствами ('input', 'index' etc). Если совпадений нет, то оба метода работают одинаково, возвращая null или false (6-ой пункт 15.10.6.2 ECMA-262).
1. Можно подробнее?
2. Если значения разные, то === отработает быстрее
www.rockstarapps.com/samples/performance/
3. В статье приведены все базовые примеры. Можете поделиться ссылкой, где написано, что
test — эквивалент RegExp.prototype.exec(string) != null

У меня сомнения, что в IE так

Цифры можно получить из примеров в статье. Это совсем не сложно. Потом еще есть
dromaeo.com/?dromaeo
1. if (a && b) {} — если 'a' — не существует, то чего будет?
2. разницы нет в алгоритме для значений одного типа; по ссылке не нашёл нужного.
3. ECMA-262 пункт 15.10.6.3.

В общем, тестов нет, жаль, половина из написанного была бы опровергнута, а другая половина вышла бы разнонаправленной. ;)
UFO just landed and posted this here
2. под IE прогоните — разница есть
3. IE так сильно придерживается ECMA? хмм, лол :)
Что стоит прогнать предложенные варианты кода в цикле по 50000 раз и просто убедиться?
2. Мило, от обобщений перевели стрелки на один движок, какой IE? 6-ой, 8-ой? что прогнать? статья льёт воду — там на 20% медленнее, здесь на 10-40%, где там? в каком движке? где тесты? я со всем готов согласиться, если пройдусь по вашим тестам и получу похожее.

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

что стоит прогнать
Прогоню с удовольствием, выкладывайте.
я конкретно запускал под IE6/7. 8 меня не очень волнует — пока еще он долю наберет.

Как только я соберу окружение с матрицей всех вышеуказанных тестов — дам ссылку. Прежде, чем делать какие-либо выводы каждый случае прогонял в Firebug (иногда и в IE7).
Спасибо. Теперь очевиднее. Проверил в IE6/FF3.0.1/Op9.63/Chr0.2. Между строгим и нестрогим сравнением ожидаемо разницы нет(туда-сюда летающие 1,2,3,4 процента на таких больших оборотах во всех случаях опускаю), та же самая картина со всеми условиями — простыми и вложенными (за исключением Оперы, у которой '&&' медленнее на 30%). C чем вы точно попали в точку, так это с RegExp, метод 'exec' везде кроме Хрома работает существенно медленнее, у IE дополнительно можно отметить быстрый 'search'.
неужели небеса разверзлись? :)

Стоит провести замеры в ряд тестов 10-15 — тогда разница становится очевиднее, и выплывают указанные 5-20%. Просто у браузеров большой разброс — ясными бывают только значительные разрывы в производительности.
ОК, каждый может сам сделать свои выводы, проверив в вышеуказанных версиях браузеров, я сделал для себя такие:

1. строгое сравнение значений одного типа по стандарту ничем (буква в букву) не отличается от нестрогого сравнения, приведённый тест это лишний раз подтверждает;

2. наглядный 'if-else' не уступает в скорости ни '&&', ни ":?", соответственно, использовать последние ради одной только скорости, а не ради игры на 'expression vs. statement' или ради сокращения кода — глупо;

3. метод 'test' несмотря на стандарт очевидно оптимизирован, метод 'exec', наоборот, не оптимизирован (кроме хитрого Хрома), 'exec' и 'test' работают одинаково (по стандарту) при отсутствии совпадений (выброс null/false), при их наличии производительность 'exec' падает (видимо) за счёт возвращаемого значения.

И общий вывод: как правило, ссылка непосредственно на сам тест в разы полезнее, чем проза в стиле «нужно иметь в виду, что производительность таких конструкций бла-бла-бла примерно на 10-50% меньше, чем бла-бла-бла». Когда примерно туда-сюда, когда большие разбросы, когда не указаны движки (версии), когда нет обоснований/предположений, а еcть одни обобщения на базе тестов в Firebug!!!, то это вообще ни о чём. Начитается эдакого доверчивая душа и ради гонок откажется от 'if-else', от нестрогого сравнения, начнёт делать всякие глупости вроде «быстрого» сложения значений или проверки на существование в стиле 'if(x)'…

p.s. за тест спасибо ;)
UFO just landed and posted this here
UFO just landed and posted this here
еще один хороший комментарий. Не помню, зачем кэшировался этот вызов. Но сейчас создавать такую переменную нет нужды — у нас всего одно обращение к string.charAt(0)
UFO just landed and posted this here
проверка тега оказалась на 40% быстрее даже в IE
UFO just landed and posted this here
Сумма говорите? :) a + b + c == 6 для 2 2 2, например. :)
это было актуально для нескольких indexOf :)
Улучшение читаемости стопки ифов перед одним со сложным условием — крайне спорный вердикт.
попробуйте записать в строчку десяток условий :). Например,
if ((!id || item.id === id) && (!klass || klass.test(item.className)) && (!attr || (_.attr[eql] && (_.attr[eql](item, attr, single[6]) || (attr === 'class' && _.attr[eql](item, 'className', single[6]))))) && !item.yeasss && !(_.modificators[modificator] ? _.modificators[modificator](item, ind) : modificator))
Пробовал. А вот разворачивать вот это вот в большущее дерево даже бы ради эксперимента над нервами не стал.
:) кому как удобнее. Главное, что работает одинаково быстро
Ищу в подстроке обычно вот так: if (str.indexOf('abc')+1).
Если вернётся что угодно, то true, если -1 — то выйдет 0, т.е. false.

Как у такого варианта с производительностью по сравнению с !=-1?
было одинаково, когда я проверял месяца два назад. Но кода чуть меньше :)
в теории — медленнее, так как 0 !== false
смешно все это ))
Раз уж вы «такты» считаете, можно убрать регулярку для ие в поиске по имениКласса.
то есть заменить вот это:

     klass = new RegExp('(^| +)' + klass + '($| +)');
     var nodes = root.getElementsByTagName('*'),
         i = 0,
         node;
     while (node = nodes[i++]) {
         if (klass.test(node.className)) {
             sets[idx++] = node;
         }
     }

вот на такое:

     klass = ' ' + klass + ' ';
     var nodes = root.getElementsByTagName('*'),
         i = 0,
         node;
     while (node = nodes[i++]) {
         if ((' ' + node.className + ' ').indexOf(klass)) {
             sets[idx++] = node;
         }
     }
о спасибо, долго думал, как избежать регулярки :)
Кстати, я как то в порядке эксперимента пробовал устанавливать временные styleSheets для поиска по css-селектору, в лоб это работало очень медленно, но может это будет хорошим способом узнать актуальность выборки из кэша:

(function (){

    var css = CSS.add(), // закроссбраузенный элемент коллекции document.styleSheets
        defaultView = document.defaultView;

    var isActualNodeBySelector = function (selectorFromCache, nodeFromCache) {
        css.insertRule('*{cursor:default}', 0);
        css.insertRule(selectorFromCache + '{cursor:crosshair}', 0);
        if (( defaultView ?
                defaultView.getComputedStyle(nodeFromCache, null) :
                node.currentStyle
            )['cursor'] == 'crosshair'
        ) {
            // .......... выборка из кэша актуальна
        }
        css.deleteRule(0);
        css.deleteRule(1);
    }
})()
Sign up to leave a comment.

Articles