Комментарии 14
Спасибо. Было полезно!
На просторах гитхаба для сафари нашёл что-то типо полифила, хотя работает оно скорее всего не так же, т.к. там используется setTimeout.
Да, тоже его видел, там действительно на setTimeout и это скорее на данный момент единственное похожее решение (по крайней мере я других не вижу пока что). Когда нибудь и они поддержат этот метод:)
Уже представлено в технолоджи превью https://developer.apple.com/documentation/safari-technology-preview-release-notes/stp-release-178
Отличная статья
Посмотрите, пожалуйста, какая метрика будет, если использовать setTimeout:
isOpenedCollapse ? getFilterData() : setTimeout(getFilterData(), 0);
В данном случае пришлось поставить задержку процессора в производительности, так как на мощных компах (которые есть не у всех пользователей) разницы практически нет.
Какой итог?
При применении setTimeout(getFilterData,0) расчет начинается после прохождения цикла в EventLoop и возникает такая ситуация:
- Просчитались открытые категории
- Сайдбар открылся
- Нажать никуда не получается, так как начал отрабатывать колбек из таймаута и начались расчеты закрытых категорий, а пользователь в это время теряет интерактивность, так как еще не все успело подгрузиться и отрисоваться
При применении requestIdleCallback такой проблемы с потерей интерактивности интерфейса замечено не было (пробовал несколько раз)
У вас, блин, какие-то КЛИЕНТСКИЕ расчеты занимают секунду и вас это не беспокоит, но беспокоит когда и что рисовать?? Вот она - проблема доморощенных программистов без базовых знаний.
Какой у вас там алгоритм для «расчетов»? O(n^10)?
Проблема не в сложности алгоритмов, а в количестве прилетаемых данных. Сложность O(n^2), так как идет маппинг по категориям (их максимум 5) и дальше внутри категорий раскидываются данные по компонентам фильтров в зависимости от вида фильтра. При этом данные уже преобразованные, поэтому дополнительных преобразований не производится, кроме как просто распределения данных по компонентам.
И как я и писал проблема возникает только при большой выдаче, так как фильтров может прилететь очень много.
Можно сказать, что это бред, но как я и сказал - это внутренний продукт и достаточно специфичный и из-за такой специфики возникают такие сложности, поэтому прошу не переходить на оскорбления
Данных не может быть СТОЛЬКО. У меня на миллионах строк на клиенте алгоритмы отрабатывают быстрее секунды, а тут фильтры… O(n^2) - это значит что вы не заморачивались с алгоритмом, я на 100% уверен, что там можно сделать как минимум O(n*log2n) и процентов на 50, что можно и O(n).
Там просто незачем проходить что-то в двух циклах, при этом не используя ни деревья ни хэш-таблицы…
Я могу вам показать тоже внутренний проект, где тоже много фильтров и они тоже пересекаются и даже пользователь сам может создавать свои фильтры на псевдо-SQL языке и они применяются к набору данных в 70 миллионов строк меньше чем за секунду :)
Ничего не тормозит нигде, без всяких шаманств с браузером.
Я за 28 лет опыта уже такого повидал выше крыши, даже похожие алгоритмы с «маппингом» исправлял. Такие проблемы - как минимум повод пересмотреть архитектуру проекта.
P.S.: Про доморощенного программиста - это не оскорбление, а предположение. Или у вас есть профильное математическое образованием знание базы в виде как минимум программы матфака, устройства ПК и опыта разработки на ассемблере и C/C++ и я не прав? Опять же, по характеру «проблемы» и выбранному способу её «решения» я предположил то, что написал.
Да, техническое образование у меня есть, в котором присутствовал и ассемблер и C++. И я бы с удовольствием взглянул на ваш алгоритм, возможно действительно можно улучшить, так как я вполне осознаю, что это на данный момент временное решение и по хорошему улучшить алгоритм отрисовки
Способ решения выбран был просто - необходимо сделать быстрее в короткий срок без долгих обдумываний и переделок. Плюс это новый метод, который хотелось опробовать и который неплохо справляется в данной ситуации
Алгоритмов там на 2407 строк C++ кода (расширение для PHP) + 3570 строк кода сам PHP скрипт, функционал - динамическое сравнение групп AB-тестов.
До перевода кода на C++ в расширение этот же функционал рендерил страницу около минуты и потреблял больше 2 ГБ памяти. Сейчас - меньше секунды.
Как можно поменять ваш алгоритм - самое простое - вместо внутреннего цикла берите данные из map-а, а сам внутренний цикл вынесите наружу и поменяйте код на заполнение этого map-а. Получится O(n * log2n), если map будет hash_map, то получится O(n). Осталось придумать что в хэше будет ключом.
Отрисовка должна быть однопроходной в принципе. Все алгоритмы должны быть не в отрисовке, а в формировании данных так, чтобы отрисовка была однопроходной.
Спасибо за статью, очень информативное изложение!
Ускорение в 30 раз — requestIdleCallback