Нестабильная Сортировка В Javascript

Когда я вижу пост на подобную тему в любой социальной сети, то почти всегда много комментариев вот такого типа:

  • Зачем это нужно знать, если есть встроенные методы сортировки?
  • Зачем изобретать велосипед?
  • Это необходимо для прохождения собеседования, объективно больше это знать не нужно.

  • Не бывает дураков, которые работают «в любом javascript-движке», и они уже все сделали правильно
И я сам раньше думал так же, пока не присоединился к одной из ИТ-команд Ростелекома на должность фронтенд-разработчика.

Вместе мы столкнулись с очень интересным кейсом: нам нужно было создать виджет, который можно было бы интегрировать в информационные системы всех наших макрорегиональных филиалов и упростить работу операторов по выбору оптимального тарифа.



Прямо в точку

Как вы думаете, что произойдет после выполнения этого кода?

Нестабильная сортировка в JavaScript

Вроде бы ничего странного, но есть нюансы.



Дело номер один

Выполнили задачу, техническое решение, код, модульные тесты.

Бизнес-процесс тоже хорош.

При поверхностном тестировании никаких проблем обнаружено не было.

Но когда дело дошло до автотестов, начали происходить странные вещи.

Конфигурация, рассчитанная Node.js 10, в основном давала правильный результат, но иногда конфигурация отличалась.

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

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

После долгих поисков проблемы в коде ошибка не была найдена.

Тестирование проекта на разных Нодах показало, что при запуске проекта на Ноде, начиная с 11 версии, отклик всегда был стабильным.

Что и было решением этой проблемы.

Версия Node была обновлена до 12, и проблема исчезла.



Нестабильная сортировка в JavaScript



Дело номер два

На этот раз в разных версиях браузера конфигурации были разными: в Google Chrome 80 результат был правильный, а в 69 версии — нет. И тогда мы начали задаваться вопросом, почему конфигурация другая.

  • Я видел, что версии разные
  • Открыты примечания к выпуску Google Chrome
  • Обнаружено, что Google Chrome 69 — это последняя сборка, использующая версию 6 V8.
  • Открыто Примечания к выпуску V8
  • И начал просматривать все статьи между 6 и 7 версией V8.
Через некоторое время я наткнулся на статью Наведение порядка в V8 , где говорится, что с версии 7 V8 переходит на стабильный алгоритм сортировки ТимСорт , вместо предыдущего нестабильного Быстрая сортировка .

И тут сразу стало понятно, что никакой магии нет и все эти баги из-за нестабильной сортировки.



Нестабильная сортировка в JavaScript



Сортировка нюансов

Сортировка в Node.js 10.22 (движок V8 v6.8) Быстрая сортировка .



Нестабильная сортировка в JavaScript

Как видите, массив с первого скриншота изменил порядок, хотя функция сравнения всегда возвращала 0. Сортировка в Node.js 14.5 (движок V8 v7.0) ТимСорт .



Нестабильная сортировка в JavaScript

На этот раз сортировка не изменила данные.



Как продолжать жить

И что происходит в конце? Клиенты могут получать разные результаты нашего кода в зависимости от типа используемого механизма сортировки JavaScript. И если переход на новую версию решает проблему с Node.js, то заставить всех пользователей сделать то же самое со своими браузерами не получится.

Существует несколько различных решений, которые подойдут для конкретных случаев.

В нашем случае мы решили использовать реализацию алгоритма Блоковая сортировка (викисортировка) .

Да, реализация медленнее, чем родная браузерная сортировка, но теперь я уверен в стабильности результата сортировки там, где это необходимо.



Сравнение различных решений с нативной реализацией

Мы решили сравнить:
  • lodash.sortby
  • ВикиСорт адаптация JavaScript ( ВикиСорт )
  • Быстрая сортировка собственная реализация V8 (node.js 10.22.0)
  • ТимСорт собственная реализация V8 (node.js 14.5.0)
В ходе теста было создано 10 массивов со случайным сортируемым значением, каждый из которых содержал 100 тысяч объектов.



Нестабильная сортировка в JavaScript

Из этого графика можно сделать вывод: после оптимизации, проведенной движком V8, сортировка ВикиСорт не уступает родной реализации ТимСорт , хотя при первой сортировке разница весьма заметна.

И здесь Лодаш Я бы не рекомендовал это.

Более подробно результаты тестирования можно посмотреть здесь сортировка-test-js , а исходный код здесь - Тихон-Устинов/sort-test-js

Где оно стабильно?

версия Дата выпуска JavaScript-движок стабильность
Node.js 11.0.0 2018-10-23 В8 7.0.276.28 +
Node.js 10.22.0 2020-07-21 В8 6.8.275.32 -
Гугл Хром 70.0.3538 2018-10-16 В8 7.0.276 +
Гугл Хром 69.0.3497 2018-09-04 В8 6.9.427 -


выводы

  • Не верьте в «магию JavaScript», все странные случаи в этом языке имеют объяснение
  • Изучите технологии, которые вы используете
  • Прочтите официальную документацию
  • Следите за тем, что появляется в новых версиях
  • Не думайте, что все уже сделано и придумано, и вам нужно использовать только готовые решения.

Теги: #Алгоритмы #программирование #разработка #JavaScript #алгоритмы сортировки #сортировка
Вместе с данным постом часто просматривают: