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

Javascript производительности Array.map

Просто написал некоторые тестовые примеры в jsperf, чтобы проверить разницу между именованными и анонимными функциями при использовании Array.map и других альтернатив.

http://jsperf.com/map-reduce-named-functions

(извините имя URL-адреса, здесь нет тестирования Array.reduce, я назвал тест, прежде чем полностью решить, что я хочу проверить)

Простой для /while цикл, очевидно, самый быстрый, я все еще удивлен более чем 10-кратным медленным Array.map, хотя...

Затем я попробовал polyfill по mozilla https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map#Polyfill

Array.prototype.map = function(fun /*, thisArg */)
{
    "use strict";

    if (this === void 0 || this === null)
        throw new TypeError();

    var t = Object(this);
    var len = t.length >>> 0;
    if (typeof fun !== "function")
        throw new TypeError();

    var res = new Array(len);
    var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
    for (var i = 0; i < len; i++)
    {
        // NOTE: Absolute correctness would demand Object.defineProperty
        //       be used.  But this method is fairly new, and failure is
        //       possible only if Object.prototype or Array.prototype
        //       has a property |i| (very unlikely), so use a less-correct
        //       but more portable alternative.
        if (i in t)
            res[i] = fun.call(thisArg, t[i], i, t);
    }

    return res;
};

Затем я попробовал простую реализацию, которую я написал сам...

Array.prototype.map3 = function(callback /*, thisArg */) {
    'use strict';
    if (typeof callback !== 'function') {
        throw new TypeError();
    }

    var thisArg = arguments.length >= 2 ? arguments[1] : void 0;

    for (var i = 0, len = this.length; i < len; i++) {
        this[i] = callback.call(thisArg, this[i], i, this);
    };
};

Резюме результатов:

От самого быстрого до самого медленного:

  • Для простого /while (примерно то же самое)
  • Map3 (моя собственная реализация)
  • Map2 (Mozilla polyfill)
  • Array.map
  • для

Наблюдения

Интересно отметить, что именованные функции обычно намного быстрее, чем при использовании анонимных функций (около 5%). Но я заметил, что polyfill работает медленнее с именованными функциями в firefox, но быстрее в хром, но реализация собственной карты хром медленнее с именованными функциями... Я тестировал это примерно по 10 раз каждый, поэтому даже если это не совсем интенсивное тестирование ( который jsperf уже делает), если только моя удача не настолько велика, этого должно быть достаточно в качестве ориентира.

Кроме того, функция chrome map доходит до 2x медленнее, чем firefox на моей машине. Не ожидал этого вообще.

И... firefox own Array.map реализация медленнее, чем Mozilla Polyfill... haha ​​

Я не уверен, почему спецификации ECMA-262 утверждают, что map можно использовать для объектов, отличных от массивов (http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.19). Это делает функцию карты в 3-4 раза медленнее (как показано в моих тестах), поскольку вам нужно проверить существование свойства в каждом цикле...

Заключение

Разница между именованными и анонимными функциями невелика, если вы считаете, что разные браузеры работают несколько иначе.

В конце концов, мы не должны сильно оптимизировать микро-оптимизацию, но я нашел это интересным:)

4b9b3361

Ответ 1

Хорошо, в первую очередь, это не справедливое сравнение. Как вы сказали, правильная карта javascript способна использовать объекты, а не только массивы. Таким образом, вы в основном сравниваете две совершенно разные функции с различными алгоритмами/результатами/внутренними работами.

Конечно, правильная карта javascript медленнее - она ​​предназначена для работы над более крупным доменом, чем простой для более массива.