Кешируем mFilter2

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

Сейчас у меня в доступе есть сайт на 27т. товаров и цифры буду приводить для него. Настроенно 11 опций в фильтре, которые в сумме дают 420 значений-чекбоксов.


Когда-то давно первой идеей было прокешировать все возможные сочетания фильтров. Но 420 факториал это очень большое число :-). Если одно сочетание займет 1кб, то для всех возможных сочетаний не хватит всего интернета :-). Так что от этой идеи пришлось быстро отказаться.

Изучение кода класса core/components/msearch2/model/msearch2/msearch2.class.php функции getFilters выявило, что когда-то кеширование там планировалось, но не было доделано. Включение cacheTime на неделю не помогает.
{'mFilter2' | snippet : ['cacheTime' =>604800,]}
В итоге я несколько модифицировал функцию https://gist.github.com/touol/4b056ba84cdabf369e0bbed0a7d70d02
Просто добавил кеширование массивов $this->filters и $built в нужных местах.
Итог примерно такой: при 420 значений-чекбоксов и товаров в каталоге до около 4т. каталог с фильтром если уже есть кеш загружатся достаточно быстро. На каталоге с 1688 товаров 0.0566859с. Фильтрует тоже быстро. на 1688 товаров 1.8384941с.
Без кеша. Загружает 0.2720420с и фильтрует 0.1641321с.
Мнда… без кеша получилось быстрее. Это для 1688 товаров.
Пробуем на каталоге с 3599 товаров.
Без кеша. Загружает 1.2010529с и фильтрует 0.4123890с.
С кешем. Загружает 0.0744750с и фильтрует 2.8954310с.
Пробуем на каталоге с 11706 товаров.
Без кеша. Загружает 5.6253080с и фильтрует 1.6628401с.
С кешем. Загружает 0.2107990с и фильтрует 26.5550659с.

Чего-то я не понимаю О_О!
Разобрался при suggestions filter вызывается много раз и много раз загружается кеш. А он полмегабайта весит и каждый раз тратиться время. Поправил функции getFilters и Filter. https://gist.github.com/touol/fd1989021270553eafb6c9540f726965

Теперь на каталоге с 11706 товаров.
С кешем. Загружает 0.2107990с и фильтрует 0.4857960с.

В общем кеширование массива $this->filters ускоряет mFilter2. Но возможно больше поможет большой объем кеша базы данных.

И пока не понятно почему на некоторые значения неверные suggestions и не верный сам фильтр.
Разобрался. Опция с неверными значениями задана json полем в msProductData. При обновлении продукта в админке значения поля пишутся и в msProductData и в msProductOption. Фильтруем мы по msProductOption, но большая часть товаров была добавлена импортом и никто не заморачивался дописывать значения в msProductOption. И в итоге Для женщин 4000 колец вообще, а в фильтре 31 кольцо.

Год назад я тестировал скорость не кешированного mFilter2 и загрузка страницы была на уровне 10с на 4000 товаров в каталоге. Но с тех пор я обновил OpenServer и поставил mysql 5.7 вместо 5.6 и отключил антивирус.
Сейчас на удивление скорость приличная на не кешированном mFilter2 и на 11т товарах. Тогда тупила именно сборка данных из базы в массив $this->filters.

В mFilter2 встречал такие узких места:
1) На первом этапе собирается массив $ids дочерних продуктов каталога через msProducts. Если дерево дочерних каталогов сильно развлетвленное может затупить msProduct. Костыль $ids можно закешировать. встречается редко.
2) Затем $ids подается в метод getFilters которая собирает из базы значения фильтров. Здесь тупит часто и я решал кешированием как написал выше.
затем метод Filter делает $ids ресурсов подходящих под фильтер. Не тупит.
3) строятся suggestions. В чем проблема выяснилось сегодня.
4) $ids передаются в pdoPage и msProducts. Здесь тоже может затупить когда id много. Решал включением кеша в pdoPage.

Скорость работы фильтров тема многогранная. Со многими ньюансами. Описал часть встречающихся проблем. Надеюсь вам будет полезно или познавательно. С этой темой я думаю еще не раз столкнусь и возможно появяться новые более лучшие подходы, которые можно будет описать.
UPD 27.09.2022
На базе на которой я тестировал выявилась проблема. Данные опций товаров импортировали в json поле msProductData, а фильтровали по msOption. Соответственно, в msOption мало данных и фильтр работал быстро и не верно.
Чтоб не вводить в заблуждение перестроил фильтр на msProductData и протестировал.
На каталоге с 11706 товаров.
Сбор данных для фильтра из базы в массив занимает 39.1501031с
0.0003209: pdoTools loaded.
0.0542250: Fetched 11706 ids for building filters from element "mSearch2"
0.0000081: Total number of results: 11706
0.0000029: Getting filters for 11706 ids
39.1501031: Total number of filters: 421
0.0683689: Fired paginator: "pdoPage"
0.0000062: Filters retrieved
0.0008359: Loaded "modChunk" with name "tpl.mFilter2.filter.checkbox"
0.0022690: Loaded "modChunk" with name "tpl.mFilter2.filter.outer"
0.0165510: Filters templated
0.0000110: Total filter operations: 0
39.2930460: Total time
94 371 840: Memory usage
При включенном кеше и включенных 'suggestionsMaxFilters'=>10000,
Кеш фильтра 3мб
При загрузке массива фильтров из кеша 0.2206910с
фильтрация 0.8021080с
Александр Туниеков
22 сентября 2022, 08:35
modx.pro
7
1 285
+8
Поблагодарить автора Отправить деньги

Комментарии: 2

Евгений
31 октября 2022, 14:07
0
Тоже бьюсь с кешированием, обновился до последней версии, кэш создается, но толку от него нет. для меня например критично посадочные страницы, т.е первый лист они самые трафиковые, и конечно снимут нагрузку с сервера, да и приятнее получать листинг не за 800мс, а за 200. тк все эти кликания по кнопкам фильтра понятно, но до этого вообще может и не дойти. есть костыль от Ильи Уткина ilyaut.ru/cheats/caching-mfilter/ и по нему реально прирост идет. Допилил настройкой ТВ на странице, которая включала костыль для определенных страниц, но хочется что то из коробки)) напишите решение до чего добились в производительности
    Александр Туниеков
    31 октября 2022, 16:45
    +1
    Добрый день! С кешированием Я написал что у меня получилось. Кешируется массив значений фильтра и id их ресурсов. Первый запуск медленный. Это когда этот массив собирается из базы. Когда кеш массива есть показ страници и ajax-фильтрация происходит быстро. Цифры привел в статье. Сейчас не охота их заного получать.
    хочется что то из коробки
    Это не ко мне. Я не автор компонента. Обращайтесь к @Илья Уткин
    напишите решение до чего добились в производительности
    Текушее решение https://gist.github.com/touol/fd1989021270553eafb6c9540f726965
    Но оно тоже не идеальное. Сильно не парился. И не понятно почему может и работать и не работать. Например, не работает и вывод дебага начал выводить вдруг заработало.
    Если надо чтоб работало из коробки и так как надо, Илью долбите чтоб начал работать над улучшением mFilter2. mFilter2 — компонент платный. Пусть париться тот кто за это деньги получает.
    Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
    2