Кешируем mFilter2
Как кол-во товаров на сайте переваливает какую-то границу, то mFilter2 начинает жестко тупить. Переодически мне приходиться бороться с этой проблемой. В итоге изучения mFilter2 выработал пару решений.
Сейчас у меня в доступе есть сайт на 27т. товаров и цифры буду приводить для него. Настроенно 11 опций в фильтре, которые в сумме дают 420 значений-чекбоксов.
Когда-то давно первой идеей было прокешировать все возможные сочетания фильтров. Но 420 факториал это очень большое число :-). Если одно сочетание займет 1кб, то для всех возможных сочетаний не хватит всего интернета :-). Так что от этой идеи пришлось быстро отказаться.
Изучение кода класса core/components/msearch2/model/msearch2/msearch2.class.php функции getFilters выявило, что когда-то кеширование там планировалось, но не было доделано. Включение cacheTime на неделю не помогает.
Просто добавил кеширование массивов $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с
Кеш фильтра 3мб
При загрузке массива фильтров из кеша 0.2206910с
фильтрация 0.8021080с
Сейчас у меня в доступе есть сайт на 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с
Поблагодарить автора
Отправить деньги
Комментарии: 2
Тоже бьюсь с кешированием, обновился до последней версии, кэш создается, но толку от него нет. для меня например критично посадочные страницы, т.е первый лист они самые трафиковые, и конечно снимут нагрузку с сервера, да и приятнее получать листинг не за 800мс, а за 200. тк все эти кликания по кнопкам фильтра понятно, но до этого вообще может и не дойти. есть костыль от Ильи Уткина ilyaut.ru/cheats/caching-mfilter/ и по нему реально прирост идет. Допилил настройкой ТВ на странице, которая включала костыль для определенных страниц, но хочется что то из коробки)) напишите решение до чего добились в производительности
Добрый день! С кешированием Я написал что у меня получилось. Кешируется массив значений фильтра и id их ресурсов. Первый запуск медленный. Это когда этот массив собирается из базы. Когда кеш массива есть показ страници и ajax-фильтрация происходит быстро. Цифры привел в статье. Сейчас не охота их заного получать.
Но оно тоже не идеальное. Сильно не парился. И не понятно почему может и работать и не работать. Например, не работает и вывод дебага начал выводить вдруг заработало.
Если надо чтоб работало из коробки и так как надо, Илью долбите чтоб начал работать над улучшением mFilter2. mFilter2 — компонент платный. Пусть париться тот кто за это деньги получает.
хочется что то из коробкиЭто не ко мне. Я не автор компонента. Обращайтесь к @Илья Уткин
напишите решение до чего добились в производительностиТекушее решение https://gist.github.com/touol/fd1989021270553eafb6c9540f726965
Но оно тоже не идеальное. Сильно не парился. И не понятно почему может и работать и не работать. Например, не работает и вывод дебага начал выводить вдруг заработало.
Если надо чтоб работало из коробки и так как надо, Илью долбите чтоб начал работать над улучшением mFilter2. mFilter2 — компонент платный. Пусть париться тот кто за это деньги получает.
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.