Этот gist является небольшим тестом, который я написал, сравнивая производительность для 4 альтернатив для сплющивающих массивов глубина = 1 в JS (код может быть скопирован как есть в консоль гугл). Если я ничего не пропустил, то у штатного Array.prototype.flat наихудшая производительность на сегодняшний день - примерно в 30-50 раз медленнее, чем у любой другой альтернативы. Следует отметить, что 4-я реализация в этом тесте неизменно является наиболее производительной, часто достигая производительности, которая в 70 раз лучше. Код несколько раз тестировался на узле v12 и консоли Chrome.
Этот результат больше всего подчеркивается в большом подмножестве - см. Последние 2 протестированных массива ниже. Этот результат очень удивителен, учитывая spe c и реализацию V8 , которая, кажется, следует за spe c буквой. Мои знания C ++ отсутствуют, так же как и мое знакомство с кроличьей ношей V8, но мне кажется, что с учетом рекурсивного определения, как только мы достигнем окончательного подмассива глубины, для этого вызова подмассива больше не производится никаких рекурсивных вызовов (флаг shouldFlatten имеет значение false, когда уменьшенная глубина достигает 0, т. е. конечного подуровня), и добавление к сглаженному результату включает в себя итеративное зацикливание каждого подэлемента и простой вызов этого метода . Поэтому я не вижу веской причины, по которой a.flat так сильно страдает от производительности.
Я подумал, что, возможно, тот факт, что в исходной квартире размер результата не был предварительно выделен, может объяснить разницу. Вторая реализация в этом тесте, которая не была предварительно выделена, показывает, что это само по себе не может объяснить разницу - она все еще в 5-10 раз более производительна, чем собственная квартира. Что может быть причиной этого?
Протестированные реализации (порядок одинаков в коде, хранящемся в массиве реализаций - два, которые я написал, находятся в конце фрагмента кода):
- Моя собственная реализация уплощения, которая включает предварительное распределение окончательная сглаженная длина (таким образом избегая размера всех перераспределений). Извините за код императивного стиля, я собирался добиться максимальной производительности.
- Простейшая наивная реализация, циклически проходящая по каждому подмассиву и вставляющая в финальный массив. (таким образом, рискуя перераспределением многих размеров).
- Array.prototype.flat (native flat)
- [] .concat (... arr) (= расширение массива с последующим объединением результатов. Это популярный способ выполнения глубина = 1 выравнивание).
Протестированные массивы (порядок кодов, сохраненный в объекте тестов):
- 1000 подмассивов по 10 элементов в каждом. (10 тыс. Всего)
- 10 подмассивов по 1000 элементов в каждом. (10 тыс. Всего)
- 10000 подмассивов по 1000 элементов в каждом. (Всего 10 мил)
- 100 подмассивов по 100000 элементов в каждом. (Всего 10 мил)