Производительность простых и сложных конструкций в JavaScript

    Периодически натыкаясь на статьи, посвященные оптимизации кода на JS (вот одна из популярных) я ловил себя на мысли, что информации в них катастрофически мало. Перечислены 2-3 конструкции, 1-2 браузера и все на этом.

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

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

    Upd: добавил графики результатов, предоставленные хабраюзером deerua (для тех, кто воспринимает визуальную подачу информации лучше чем табличную)

    Введение


    Итак, машина для тестирования — P4 3GHz (двухядерный), 1.5RAM, Vista 32-bit.
    Набор браузеров — FF3, Opera 9.62, Chrom 1.0, IE7, IE8b2

    Скажу сразу, что IE8 — не оригинальный, а запущенный через программу IETester
    Насколько он соответствует оригинальному я не знаю, но по крайней мере от IE7 результаты отличаются довольно сильно, причем в различные стороны.

    Если кто-то хочет протестировать IE6 или любой другой браузер — собственно, welcome )

    Методология тестирования


    Все нижеописанные языковые конструкции тестировались путем повторения 1 миллион раз в цикле. Данное действие повторялось несколько раз в каждом браузере, дабы выявить некий средний результат (он обычно колеблется в пределах +-2-5% в зависимости от текущей загрузки системы). Средний результат (в миллисекундах) записывался в таблицу.

    Везде (где явно не указано другое) использовался инвертированный цикл for(var i=1000000; i--;) как наиболее быстрый.

    Переходим к делу


    Циклы


    Тесты/Браузеры FF3 Opera Chrome IE7 IE8b2
    Циклы
    Классический цикл 71 100 16 238 218
    Инвертированный цикл 34 34 7 70 118
    while-цикл 30 33 7 70 118


    Итак, для начала я решил протестировать сами циклы (просто пустые циклы без выполняемого кода внутри). Т.к. сказать основу нашего тестирования )
    Про циклы уже было написано довольно много, так что результаты вполне предсказуемы.
    Как видно, инвертированный цикл for(var i=1000000; i--;) как минимум вдвое быстрее классического for(var i=0; i<1000000; i++), поэтому именно он использовался в дальнейшем тестировании.
    Также можно заметить что while цикл практически не отличается по скорости от инвертированного for, видимо потому что это фактически одна и та же конструкция (по логике работы).

    Работа с массивами и объектами


    Тесты/Браузеры FF3 Opera Chrome IE7 IE8b2
    Перебор массивов и объектов
    Получение значений большого массива (1M) по индексу (полный перебор в обратном порядке) 430 170 18 790 1020
    Получение значения маленького массива (100) по индексу 124 146 18 428 515
    For-in цикл по объекту (1M) 2020 2160 385 39400 35400
    Перебор объекта (1M) через инвертированный цикл 390 170 18 745 746
    Заполнение массивов и объектов
    Заполнение (1M) массива через array.length 190 485 82 2640 865
    Заполнение (1M) массива в прямом порядке через значение шага цикла (классический цикл) 200 432 75 2500 760
    Заполнение (1M) массива в обратном порядке через значение шага цикла (инвертированный цикл) 1180 310 124 2270 2260
    Заполнение (1M) массива через push() 176 1120 98 4450 1186
    Заполнение объекта (1M) в прямом порядке через значение шага цикла (классический цикл) 1080 368 74 2400 2205


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

    Массив (или объект) 1M — имеется ввиду массив (или его заменитель) с кол-вом элементом равным 1000000, ну и индексами (ключами) соответственно от нуля до миллиона (точнее, 999999).

    В первом тесте мы полностью перебираем такой массив в инвертированном цикле, т.е. примерно вот так:
    var a=0;
    for(var i=1000000; i--;) {a=big_array[i];}

    Во втором тесте мы также делаем миллион итераций цикла, но на каждом шаге получаем одно и то же значение из маленького массива (размером 100 элементов). Этот тест я сделал для проверки того, насколько размер массива влияет на скорость получения из него значений.
    Как показал тест, во всех браузерах кроме Chrome время поиска значения в массиве может значительно возрасти с ростом кол-ва его элементов.

    В третьем тесте делается полный for-in цикл по объекту-заменителю массива.
    Хорошо видно что цикл for-in является очень медленным во всех браузерах (по сравнению с инвертированным for), и ОЧЕНЬ медленным в IE для больших объемов данных. Никогда не используйте его для перебора массивов или объектов, где можно обойтись циклом for (т.е. ключи числовые и упорядоченные).

    Четвертый тест — полный аналог первого теста, кроме того что big_array является не массивом а объектом.
    Заметно, что скорость перебора через цикл слабо зависит от того, массив у нас или объект-заменитель. Ощутимая разница только в IE8, но это еще бета, так что все может измениться.


    Также стоит заметить, что если перед нами стоит задача выбрать диапазон элементов массива то использование метода array.slice() в любом браузере в несколько раз быстрее, чем просто перебор массива в цикле с выборкой нужных элементов по условию. Разница настолько очевидна, что я даже не стал включать это в тест.

    Помимо перебора массивов, часто приходится их заполнять, поэтому следующие 5 тестов как раз об этом.
    В принципе, из таблицы все должно быть понятно:
    • Заполнение массива через метод push значительно медленнее во всех браузерах, кроме FF, по сравнению с заполнением через array[array.length]=value. (Разработчики огнелиса видимо единственные поняли, что это полное безобразие, когда вместо родного метода используется громоздкая конструкция.)
    • В некоторых браузерах бывает важно, заполняете ли вы массив в прямом или обратном порядке.
    • Заполнение объекта-заменителя значительно медленнее в FF и IE8, видимо потому что операция заполнения массива специально оптимизирована, а заполнения объекта — нет (что и понятно, потому что объект не должен использоваться вместо массива для хранения больших объемов однородных данных).




    Функции, объекты, переменные


    Функции, объекты, переменные
    Тесты/Браузеры FF3 Opera Chrome IE7 IE8b2
    Вызов пустой функции с передачей ей текущего значения цикла 129 270 17 3100 860
    Создание объекта (создание 2-х методов и одного свойства через конструктор) 2460 1900 593 18600 11700
    Создание объекта (создание 2-х методов из прототипа и одного свойства через конструктор) 1260 636 64 7830 4210
    Получение свойства объекта (собственное свойство) 84 142 16 406 412
    Получение свойства объекта (свойство прототипа) 90 147 29 474 474
    Получение свойства объекта (метод-геттер приватного var свойства) 260 354 33 3430 1160
    Вызов инкрементного метода объекта (увеличивает собственное свойство через this) 326 460 60 3810 1520
    Вызов инкрементного метода объекта (увеличивает собственное свойство через явное указание объекта) 356 520 65 3985 1633
    Вызов инкрементного метода объекта (увеличивает приватное var свойство) 412 370 38 3530 1320



    В первую очередь, я протестировал вызов пустой функции в цикле.
    var f=function(){}
    for(var i=1000000; i--;) {f();}

    В большинстве браузеров вызов функции является довольно дешевой операцией (на миллион вызовов всего несколько сотен добавленных миллисекунд, по сравнению с полностью пустым циклом).
    Однако IE, как всегда, преподносит неприятные сюрпризы. Любителям оборачивать код во множество функций-оберток будет над чем подумать )

    Отмечу, что медленный вызов функции как таковой отрицательно влияет и на другие тесты, связанные с вызовом функций (например, создание объекта или вызов метода), поэтому время их выполнения в IE еще сильнее увеличивается.

    Следующие 2 теста посвящены созданию миллиона объектов, в одном случае все методы создаются через конструктор, в другом — через прототип.
    Разница, я думаю, очевидна.

    Три следующих теста вызывают свойство объекта: собственное свойство (созданное через this.prop=value), свойство прототипа и приватное свойство (созданное через замыкание из функции конструктора). Очевидно, что последний вариант получаем через геттер.
    Результат, в общем, предсказуем — собственное свойство объекта можно получить значительно быстрее.

    Далее следует 3 теста, вызывающих инкрементный метод объекта (т.е. метод, которая при каждом вызове увеличивает свойство объекта на единицу). Собственно, разница здесь опять же в том, как именно данное свойство было создано (т.е. тестируется скорость доступа к свойствам объекта из его же методов).
    Наглядно видно, что в данном случае скорость изменения приватного свойства выше везде, кроме Firefox, однако нужно помнить, что такое свойство является общим для всех однотипных объектов и имеет худшее время чтения снаружи (через геттер).

    Ветви


    Ветви
    Тесты/Браузеры FF3 Opera Chrome IE7 IE8b2
    Выбор ветви из 8 возможных через if 800 500 60 1500 1460
    Выбор ветви из 8 возможных через switch 315 334 54 868 1039
    Выбор ветви из 8 возможных через хэш функций 620 400 86 4520 1820



    Первые два теста в этой таблице я думаю комментировать не нужно, на третьем остановимся поподробнее.
    Хэш функций — это объект, эмулирующий своим поведением switch.
    Например, у нас есть такой кусок кода:
    switch(a) {
    case 0: b=6+2; break;
    case 1: b=8*3; break;
    }
    Тогда хэш функций будет выглядеть так:
    hash={
    '0': function() {return 6+2;},
    '1': function() {return 8*3;}
    }
    И использоваться так b=hash[a]();

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

    Общий вывод по браузерам


    Опять же все предсказуемо. Chrome уверенно лидирует с отрывом в несколько парсеков, огнелис и опера делят друг с другом второе и третье место (в разных тестах по разному), ослик уныло плетется в конце, однако бета-ослик подает некоторые надежды на то, что пациент скорее жив, чем мертв.

    Заключение


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

    С другой стороны, тот метод, который сегодня вызывается сто раз, завтра может вызываться уже десять тысяч раз, так что совсем уж махать рукой на это дело не стоит. И если что-то где-то начало тормозить, будет хотя бы понимание, в какую сторону следует «копать» )

    Similar posts

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 60

    • UFO just landed and posted this here
        +5
        Firefox 3.1 с новым JS-движком TraceMonkey должен показывать схожие результаты
        +2
        Стоит добавить, что при оптимизации приложений в первую очередь стоит оптимизировать логику, а не js-конструкции.
          +1
          Ну оно вроде как друг с другом связано )
          Логика то в конечном итоге через конструкции и выражается.

          Кроме того, некоторые решения могут быть очень логичными и правильными с точки зрения архитектуры, но не оптимальными с точки зрения производительности в конкретном узком месте. Тут уже как обычно надо искать «золотую середину».
            +3
            Позволю не согласиться :)

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

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

              Во-вторых, непонятно, что значит экономия на спичках.
              Вот конкретно пара примеров — есть прямой цикл, есть обратный. Обратный в 2-3 раза быстрее. Да, разница в абсолютном показателе невысока, но зачем делать медленно если можно сделать быстро (при условии что порядок перебора не важен)? Инвертированный цикл даже короче в записи.

              Еще пример — приватные и обычные свойства объекта. Некоторые любят понаделать приватных свойств, понаписать к нем геттеров (как привыкли в других языках), и потом копеечка к копеечке интерфейс может начать тормозить. Тесты наглядно показывают, чем это может грозить.
                +1
                Вы все правильно сказали: «разница в абсолютном показателе невысока».
                Прирост в несколько миллисекунд — это и есть экономия на спичках.
                  0
                  Я там еще правильно сказал — зачем делать медленно, если можно делать быстро с теми же трудозатратами?
                  Вот вам если ДедМороз предложит совершенно бесплатно взять 10 000 рублей или 9 960, на выбор — вы что возьмете? Разница то вроде невелика.
                    +1
                    из-за того, что разница невелика, я возьму то, что удобнее положить в кошелек :)
                    или в случае програмимрования легче читается, понимается и поддерживается.

                    микрооптимизация, к сожалению, не приносит желаемых результатов. Конечно, не стоит совсем о ней забывать, и ваша статья хороша для понимания правильных конструкций. Но, как я уже говорил, в первую очередь надо искать узкие места в алгоритмах.
                      0
                      Полностью согласен. Я выберу именно прямой цикл, потому как данная конструкция более привычна большинству программистов — молодой специалист не запутается в моем коде.
                        0
                        Полностью согласен. Я выберу именно прямой цикл, потому как данная конструкция более привычна большинству программистов — молодой специалист не запутается в моем коде.
                          0
                          офтоп: жаль, что удалять нельзя
                    0
                    есть полуюмористическая метрика качества кода по количеству «WTF?!» при его чтении

                    каждый обратный цикл будет порождать лишний WTF, потому что логикой кода никак не обоснован

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

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

                        прямой более логичен по той же причине, по которой вы помните алфавит, начиная с первой буквы, а не наоборот. Или я ошибся?; )
                          0
                          Хм, алфавит говорите… Вот у вас в коробке лежат 33 вырезанные из картона буквы русского алфавита. Ваша задача — перекрасить их все в зеленый цвет, вытаскивая по одной.
                          Вы как будете буквы перекрашивать: в алфавитном порядке или просто в порядке доставания из коробки?

                          Да, согласен, какие-то нестандартные или даже просто немного непохожие на классику конструкции могут вызывать определенные сложности у некоторых людей, но это не повод не использовать их при написании скриптов. Потому что, повторюсь, нормального программиста нестандартные конструкции не испугают. А если их нестандартность оправдана, то еще и добавят ему в копилку немного опыта.
                            0
                            нет, лежат они не в коробке, а выложены в линию по порядку. Очень сомневаюсь, что в этой ситуации вы начнёте красить справа или снизу

                            сложности — ещё какой повод! Ну если только вы не пишете перловые однострочники или другой write-only код. Про «нормального программиста» у вас очень субъективное мнение ; )

                            и вообще, пишите уже на Forth тогда ; )

                            ладно, не буду вас дальше переубеждать, мне с вами не работать, бесполезная трата слов получается
                0
                не всегда :) Например, если у нас есть цикл с регулярками, который выполняется, ну пусть, 100 раз, то тормозить будет заметно. Если же ту же самую логику записать с помощью хэшей или сравнений, то прирост производительности на лицо.
                0
                Ветви через hash функции впервые увидел, этакий мутант из обьекта с параметрами…
                  0
                  Иногда бывают такие штуки, что в switch их писать неудобно (по разным причинам, например код излишне дублируется или не хочется лишними переменными засорять текущий контекст). Тогда хэш может помочь. По сути, это такой полиморфизм на лету.

                  Можно вообще так писать:
                  ({'one': obj.method, 'two': function(i) {return obj2.method3(i)*18}, 'three': function(){return false}})[value](i);
                  Хотя не факт что нужно )
                    0
                    Для меня, пишущего на c#, выглядит ужасно =)
                    Хотя понятно конечно что hash в редких случаех удобнее, в нём нельзя например как в switch указать
                    case 21:
                    case 22:
                    case 23: doSomething(); break;

                    и нету замены для default
                    но нельзя не согласиться что иногда это может быть удобно.
                      0
                      switch (..) {
                      case 21:
                      case 22:
                      case 23: doSomething(); break;
                      }


                      hash[21] = hash[22] = hash[23] = function(){ doSomething(); }


                      switch (..) {
                      case 21: doSomething1();
                      case 22: doSomething2();
                      case 23: doSomething3(); break;
                      }


                      hash[21] = function(){ doSomething1(); };
                      hash[22] = function(){ hash[21](); doSomething2(); };
                      hash[23] = function(){ hash[22](); doSomething3(); };


                        0
                        Не, ну default он для вообще непредвиденных значений.
                        Тут единственный способ эмуляции — ловить undefined при попытке вызова метода хэша, которого не существует и дальнейшая обработка.
                        Что собственно еще добавляет кривизны коду.
                        Так что это все для весьма редких случаев.
                          0
                          А, сори, затупил, это про break и другие свойства switch, а не про default
                  –2
                  это что за цифры? количество секунд, миллисекунд, минут, часов, загрузка процессора?

                  Хорошо было бы указать единицы измерения. Без них результаты ни о чем не говорят. Всегда
                    +3
                    Данное действие повторялось несколько раз в каждом браузере, дабы выявить некий средний результат (он обычно колеблется в пределах +-2-5% в зависимости от текущей загрузки системы). Средний результат (в миллисекундах) записывался в таблицу.
                    Под заголовком методология написано.
                    0
                    Как мне видится, лучшая оптимизация — это поиск повторяющихся мест и создание единой функции для выполнения часто повторяющихся действий (или же обьёмных по коду), это позволяет разделить код на отдельные части которые станет визуально проще анализировать.

                    Например код сравнения двух массивов:
                    Array.prototype.Equals = function(value) {
                      if (value.constructor != Array) return false;
                      if (this.length != value.length) return false;
                      var ar1 = new Array().concat(this);
                      var ar2 = new Array().concat(value);
                      var result = ar1.sort().toString() == ar2.sort().toString();
                      delete ar1;
                      delete ar2;
                      return result;
                    }


                    * This source code was highlighted with Source Code Highlighter.


                    пока что для себя я нашёл такой способ наиболее оптимальный, но для небольших массивов.
                    Предполагаю что с увиличением массива такой метод будет требовать больше времени, причём в геометрической прогрессии…
                      0
                      Немного непонятна логика метода Equals, тот момент где сортировка происходит.
                      Даже если массивы имеют одинаковый набор элементов, но разный их порядок — называть их эквивалентными как-то неправильно по-моему.

                      А по существу — если не делать сортировку, то
                      Array.prototype.Equals = function(value) {
                        if (value.constructor != Array) return false;
                        if (this.length != value.length) return false;
                        for(var i=this.length; i--;) {
                          if(this[i]!==value[i]) return false;
                        }
                        return true;
                      }


                      * This source code was highlighted with Source Code Highlighter.

                      в десятки (в некоторых случаях в сотни) раз быстрее, жрет меньше памяти и меньше места в коде.
                        0
                        О, спасибо!
                        Я почему-то сразу не подумал, или упустил этот вариант, и не надо копировать массивы, потом удалять их, шикарно =)
                        Про сортировку верно подмечено, не продумал (=
                        0
                        создание единой функции...
                        Тут важно, чтобы не захотелось сделать тоже самое с прототипом Object: из-за этого желания проход по всем свойствам объекта уже нельзя будет сделать простым for (i in Obj) {… }, что повлечёт за собой дополнительные затраты ресурсов (как минимум на hasOwnProperty)
                          0
                          Чего-то я только сейчас подумал, если сравнить две коллекции используя ===
                          именно 3 равно, что сравнивает не только тип, но и value.
                          Подозреваю конечно что ничего не даст, но как доберусь до лома, обязательно проверю…
                            0
                            Не даст ничего потому, что array — это объект, а с объектами работа только по ссылке. Таким образом получить true можно только сравнивая массив сам с собой, либо две ссылки на один и тот же массив.
                            ar=[];
                            ar2=ar;
                            alert(ar==ar2); //true
                            И даже точного сравнения не надо.
                              0
                              Да, точно, видимо это-то меня и смущало когда я писал пост =)
                              0
                              > используя === именно 3 равно, что сравнивает не только тип, но и value.

                              наоборот (вероятно, опечатка) — что сравнивает не только value, но и тип
                                0
                                да, спасибо, перепутал местами
                              0
                              > var ar1… delete ar1;

                              var'ы, созданные не через eval, удалить нельзя (они все получают внутреннее свойство {DontDelete})
                                0
                                Хм, это дляменя новость, как-то не смотрел в этом направлении почти, потмоу навернео и не знаю.
                                А eval как я помню зло…
                              0
                              А можно заголовки с названиями браузеров во все таблицы добавить?
                              В 3 и 4 запутался где какой браузер.
                                0
                                добавил.
                                я собственно и собирался во все добавить изначально, но видимо глаз замылился и не заметил
                                0
                                при тестировании ветвления к какой из ветвей вы получали доступ? случайной, фиксированной или последовательно ко всем?

                                если не трудно, можете сделать тест для переменного числа ветвей (от 1 до 10, например)?
                                  0
                                  Там все просто было, брался шаг цикла (от нуля до миллиона соответственно) и делился с остатком на число ветвей (a=i%8, где a — условие ветви, i — шаг цикла, 8 — кол-во ветвей).
                                  Таким образом можно получить равномерное распределение по всем ветвям.
                                  Соответственно, в каждом из тестов и на каждом прогоне ветви вызывались в одном и том же порядке и пропорциях.
                                    0
                                    сделать тест для переменного числа ветвей (от 1 до 10, например)
                                    Да по-моему не имеет смысла.
                                    Для 1-2 ветвей вообще проще всего использовать тернарный оператор, как вот ниже в комментах написали.
                                    Для большего кол-ва ветвей интуитивно понятно, что switch будет работать быстрее чем множественные if else, к тому же предоставлять больше возможностей. Причем чем больше ветвей, тем больше разница во времени выполнения.
                                    +1
                                    Ещё бы исходнички, я бы на Опере 10 потестил
                                      0
                                      Да там нету как таковых исходников. Я сначала хотел все по правильному сделать, для каждого теста свою функцию и ее вызывать в цикле, но после того как увидел, сколько функция сама по себе выполняется…

                                      В итоге пришлось для каждого нового теста комментить старый код внутри тела цикла и писать новый.
                                        +1
                                        Вот, если хотите, по самим циклам тесты (те, которые первые в статье):
                                        var loop=1000000;

                                        function start() {time=new Date();}
                                        function end() {document.write("
                                        "+(new Date() - time));}

                                        var cicles={
                                        'classic_cicle': function(){for(var i=0; i<loop; i++) {}},
                                        'invert_cicle': function(){for(var i=loop; i--;) {}},
                                        'while_cicle': function() {var i=loop; while(i--) {}}
                                        }

                                        start();
                                        cicles.classic_cicle();
                                        end();
                                          0
                                          Opera 9.0 — 450
                                          Opera 9.51 — 156
                                          Opera 10.00 alpha — 145
                                          Opera 6.05 — 1170 :)
                                            0
                                            Opera 10.00 alpha — 145
                                            Opera 6.05 — 1170 :)

                                            Хорошо что так, а не наоборот )
                                              0
                                              IE4 — 250
                                              IE5.01 — 200
                                              IE5.5 — 260
                                              IE6 (must die) — 320
                                              IE8 beta2 — 310
                                        0
                                        1000000 записей… ммм я не часто такое количество обьектов вижу =) а темболее в виде хеша
                                        может я ошибаюсь, но это не совсем корректный способ тестирования скорости
                                          0
                                          > он обычно колеблется в пределах +-2-5% в зависимости от текущей загрузки системы
                                          А загрузка системы разве не должна быть нулевая во время тестирования?
                                            0
                                            Ну я естественно не запускал никаких тяжелых приложений во время тестов (собственно, вообще все закрыл кроме браузеров), но винда периодически может выполнять какие-то свои внутренние задачи, которые жрут немножко процессорного времени.

                                            Для этого каждый тест в одном браузере и прогоняется несколько раз, чтобы понять среднее значение.
                                            0
                                            Хорошая статья. Но надо понимать, что помимо производительности самого джаваскрипта, следует также учитывать (даже в большей степени) общую производительность веб-браузеров — этот вопрос хорошо осветил Сергей Чикуенок в статье «Производительность браузеров в зависимости от верстки».
                                              +1
                                              Вот тут хорошая подборка тестов
                                              www.rockstarapps.com/samples/performance/
                                                0
                                                Да, подборка действительно здоровская. Жалко что раньше не видел.
                                                0
                                                P.S. я как раз собирался писать серию статей по следам оптимизации YASS, но меня опередили немного :)

                                                Вообще говоря, быстрее хэша будет обычное сравнение, т.е.
                                                a ? b = 6+2 : b = 8*3
                                                  0
                                                  Меня кстати вот этот твой комментарий и натолкнул на мысль о статье.
                                                  Так что все взаимосвязано )
                                                  0
                                                  Ну протестируйте еще что быстрее
                                                  if (my == 'раз' || my == 'два' || my == 'три')…
                                                  или
                                                  if ({'раз',1;'два':1,'три':1}[my])…

                                                  еще я замечал
                                                  my = myArray.shift();
                                                  работает медленнее чем
                                                  myArray.reverse(); my = myArray[myArray.length-1]; myArray.length--; myArray.reverse();
                                                  вот это действительно странно, в отличии от того почему myArray.push(my) медленнее myArray[myArray.length]=my
                                                  Чтобы вызвать метод объекта нужно больше «Ку» сделать чем прочитать и записать его свойство
                                                    0
                                                    Почитаю в Хабрадайжесте))
                                                      +3
                                                      На самом деле чистого яваскрипта в веб приложениях мало. Никто ж не делает на нем числомолотилки. Поэтому такие синтетические тесты это вещь в себе. Тесты ради тестов. Ну и что, что реализация яваскрипта в Хром быстрее всех. Реальные веб приложения от этого выигрыша практически не имеют. Что-то незаметно что страницы летают во столько же раз быстрее во сколько быстрее яваскрипт в тестах. А в некоторых тестах он даже и медленнее чем IE.
                                                      Имхо основные тормоза возникают при работе с браузерными объектами — обращение к атрибутам и свойствам узлов и их изменение, создание/удаление узлов DOM, изменения innerHTML(при этом браузер чистит/меняет дерево DOM ). Работа с XML. Работа со стилями. Обработка событий. Вот где зарыты узкие места, а не в скорости интерпретации яваскрипта.
                                                        0
                                                        Хотел я про это же написать, но подумал что тема тут поставлена чётко, про производительность js, а не производительность браузера, пропускной скорости канала, и пробках на дорогах.
                                                        Наверно, судя по плюсам, я подумал неправильно. Ну что же держите еще плюс.

                                                      Only users with full accounts can post comments. Log in, please.