Url Rules. Оптимизация

Обсуждение документации второй версии фреймворка. Переводы Cookbook и авторские рецепты.
Ответить
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Url Rules. Оптимизация

Сообщение zelenin »

Итак. Подниму вопрос, о котором большинство yii-разработчиков даже не задумывалось - производительность правил урлов (Url Rule). Расскажу как это работает и в чем просадка на конкретном примере.

все мы знаем такие правила:

Код: Выделить всё

                    '<module:[\w-]+>' => '<module>/default/index',

                    '<module:[\w-]+>/<action:[\w-]+>/<id:\d+>' => '<module>/default/<action>',
                    '<module:[\w-]+>/<action:[\w-]+>' => '<module>/default/<action>',

                    '<module:[\w-]+>/<controller:[\w-]+>/<action:[\w-]+>/<id:\d+>' => '<module>/<controller>/<action>',
                    '<module:[\w-]+>/<controller:[\w-]+>/<action:[\w-]+>' => '<module>/<controller>/<action>'
 
они достаточно общие и подойдут для админки. На фронте же правила в угоду сео достаточно различны и часто не поддаются общим правилам - для каждого типа урла заводится свое правило типа такого:

Код: Выделить всё

[
        'pattern' => 'posts/<page:\d+>/<tag>',
        'route' => 'post/index',
        'defaults' => ['page' => 1, 'tag' => ''],
    ], 
На проекте есть 100 правил, конфигурируемых массивом. При инициализации фреймворка эти массивы преобразуются в объекты UrlRule - итого имеем 100 объектов, кушающих 0.5 мб памяти.
Дальше есть два сценария работы: парсинг урла и создание урла.
1. При парсинге урла мы перебираем каждое из 100 правил пока не найдем в одном из правил подходящую под урл регулярку. Как только мы нашли нужное правило, мы узнаем роут, куда направляем запрос и инициализируем необходимый контроллер.
2. При создании урла мы перебираем все правила, пока не совпадет роут урла и роут правила. При совпадении мы останавливаемся, т.к. знаем каким правилом нам генерировать ссылку.

Теперь выделим проблемы: кол-во памяти, выделяемое на объекты и неконтроллируемое кол-во итераций на нахождение нужного правила.
Во втором сценарии при 100 ссылках на странице и 100 правилах урлов мы теоретически получим до 10000 итераций для нахождения нужного правила.

Способы решения:
а) выделение групп правил (post: post/update, post/new, post/ajaxCount, post/delete, post/comment/edit) в отдельный класс.

Код: Выделить всё

  'rules' => [
      ['class' => 'PostUrlRule'],
      // ...
 ]
 
в классе при парсинге ссылки мы можем сразу сделать первичную проверку регуляркой, например ^post, чтобы отсечь сразу всю группу правил и перейти к проверке следующего правила например GoodsUrlRule.
Таким образом мы сократим кол-во объектов правил в разы, условно со 100 до 20, облегчив потребление памяти и уменьшив кол-во итераций на парсинг ссылки.
Этот пункт, скажем, хинт для разработчика.

UPD: в комментах упомянули GroupUrlRule для yii2, который решает проблему с группированием, но усугубляет проблему с памятью.

Следующий пункт - предложение для разработчиков yii (для включения в ядро или для написания расширения):
б) добавить функционал теггирования правил

Код: Выделить всё

[
        'pattern' => 'goods',
        'route' => 'goods/index',
        'suffix' => '.json',
        'tag' => 'goods'
    ],
    ['class' => 'PostUrlRule', 'tag' => 'post'],
 
это позволит задавать для определенного роута приоритетный тег с целью приоритизации определенных правил. Поясню:
Допустим у нас 100 правил, в конце массива находятся 10 правил группы post, последнее из которых (100-е) обрабатывает ссылки роута post/view. На странице у нас 100 ссылок на посты, генерируемых через createUrl. Для генерации всех ссылок придется сделать 10000 итераций.
При введении теггирования, мы можем в каком-то месте задать для роута приоритетный тег (теги или даже веса), например

Код: Выделить всё

Yii::$app->getUrlManager()->setPriorityRuleTag('post') 
, что пересортирует правила, вынеся на верх массива правила с тегом post. Для случая, описанного выше, это уменьшит кол-во итераций с 10000 до 100.

При объединении двух вариантов ваш урлменджер убыстрится до скоростей формулы 1.

PS Такие оптимизации возможно не имеют смысла для небольших проектов. Для больших эти оптимизации дадут существенный профит.
Последний раз редактировалось zelenin 2016.01.31, 19:03, всего редактировалось 1 раз.
lynicidn
Сообщения: 2222
Зарегистрирован: 2014.05.24, 15:12

Re: Url Rules. Оптимизация

Сообщение lynicidn »

документация и рецепты
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Url Rules. Оптимизация

Сообщение ElisDN »

Необходимость перебора оптимизирую группировкой в GroupUrlRule:

Код: Выделить всё

'rules' => [
    '' => 'site/index',
    [
        'class' => 'yii\web\GroupUrlRule',
        'prefix' => 'catalog',
        'routePrefix' => 'shop',
        'rules' => [
            ...
            '<id:\d+>' => 'view',
            '<id:\d+>/<_a:[\w\-]+>' => '<_a>',
            '' => 'index',
        ],
    ],
    [
        'class' => 'yii\web\GroupUrlRule',
        'prefix' => 'blog',
        'routePrefix' => 'blog',
        'rules' => [
            ...
            '<id:\d+>' => 'view',
            '<id:\d+>/<_a:[\w\-]+>' => '<_a>',
            '' => 'index',
        ],
    ],
    '<_c:[\w\-]+>/<id:\d+>' => '<_c>/view',
    '<_c:[\w\-]+>/<id:\d+>/<_a:[\w\-]+>' => '<_c>/<_a>',
    '<_c:[\w\-]+>' => '<_c>/index',
], 
Группа сразу отсекается по префиксу https://github.com/yiisoft/yii2/blob/d4 ... e.php#L117
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Url Rules. Оптимизация

Сообщение zelenin »

ElisDN писал(а):Необходимость перебора оптимизирую группировкой в GroupUrlRule:

Код: Выделить всё

'rules' => [
    '' => 'site/index',
    [
        'class' => 'yii\web\GroupUrlRule',
        'prefix' => 'catalog',
        'routePrefix' => 'shop',
        'rules' => [
            ...
            '<id:\d+>' => 'view',
            '<id:\d+>/<_a:[\w\-]+>' => '<_a>',
            '' => 'index',
        ],
    ],
    [
        'class' => 'yii\web\GroupUrlRule',
        'prefix' => 'blog',
        'routePrefix' => 'blog',
        'rules' => [
            ...
            '<id:\d+>' => 'view',
            '<id:\d+>/<_a:[\w\-]+>' => '<_a>',
            '' => 'index',
        ],
    ],
    '<_c:[\w\-]+>/<id:\d+>' => '<_c>/view',
    '<_c:[\w\-]+>/<id:\d+>/<_a:[\w\-]+>' => '<_c>/<_a>',
    '<_c:[\w\-]+>' => '<_c>/index',
], 
Группа сразу отсекается по префиксу https://github.com/yiisoft/yii2/blob/d4 ... e.php#L117
ок, но только это плодит еще больше правил, усугубляя проблему памяти, хотя частично решая проблему кол-ва итераций.
Но в таком виде мой пост конечно не имеет смысла в качестве пожелания разработчикам - лишь в качестве рецепта и запроса на расширение с тегированием.
PS заблуждался, т.к. основывался на yii1 - казалось, в этом плане ничего не поменялось.
lynicidn
Сообщения: 2222
Зарегистрирован: 2014.05.24, 15:12

Re: Url Rules. Оптимизация

Сообщение lynicidn »

думаю все же полезная статья, по крайней мере многие не понимают как строятся и парсятся правила, что их последовательность важна и прочие очевидные вещи, есл вглядеться в код.
Аватара пользователя
zabachok
Сообщения: 522
Зарегистрирован: 2013.12.16, 14:38

Re: Url Rules. Оптимизация

Сообщение zabachok »

Очень толковая идея! Возьму на вооружение. Спасибо!
2b||!2b Just read the instructions
Аватара пользователя
demimurych
Сообщения: 20
Зарегистрирован: 2016.06.27, 01:58

Re: Url Rules. Оптимизация

Сообщение demimurych »

Кто мешает создать свой собственный класс правил URL со своим преферансом и поэтессами?
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Url Rules. Оптимизация

Сообщение zelenin »

demimurych писал(а):Кто мешает создать свой собственный класс правил URL со своим преферансом и поэтессами?
кому вопрос? в статье именно про это в том числе.
Аватара пользователя
demimurych
Сообщения: 20
Зарегистрирован: 2016.06.27, 01:58

Re: Url Rules. Оптимизация

Сообщение demimurych »

zelenin писал(а):
demimurych писал(а):Кто мешает создать свой собственный класс правил URL со своим преферансом и поэтессами?
кому вопрос? в статье именно про это в том числе.
как мне показалось не вполне. Перефразирую свою ремарку.
Итак у нас есть приложение, профилирование которого показало что мы имеем существенную нагрузку в классе UrlManager связанную непосредственно с правилами.

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

Путь второй - погрузиться в ад с динамическим добавлением только нужных нам в текущий момент правил.

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

То есть, по моему мнению, в проекте который требует большого количества правил - использование классов UrlRule и GroupUrlRule не рационально, в силу того что они написаны из расчета создания простого универсального инструмента для создания правил почти любой сложности. Цена за универсальность - низкая производительность на большом количестве правил.

Иначе говоря все, что нам нужно это реализовать свой собственный класс для правила, который будет работать с нашим собственными подправилами либо вообще выстраивать весь роутинг не отталкиваясь от имен контролееров экшенов, а по какой то одной общей схеме.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Url Rules. Оптимизация

Сообщение zelenin »

в решении "а" разве не об этом?
Аватара пользователя
SiZE
Сообщения: 2813
Зарегистрирован: 2011.09.21, 12:39
Откуда: Perm
Контактная информация:

Re: Url Rules. Оптимизация

Сообщение SiZE »

demimurych писал(а): Путь второй - погрузиться в ад с динамическим добавлением только нужных нам в текущий момент правил.
URL динамически сопоставляется с правилами. Как ты собираешься заранее угадывать нужные правила? ПМСМ такого варианта не может быть.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Url Rules. Оптимизация

Сообщение zelenin »

SiZE писал(а):
demimurych писал(а): Путь второй - погрузиться в ад с динамическим добавлением только нужных нам в текущий момент правил.
URL динамически сопоставляется с правилами. Как ты собираешься заранее угадывать нужные правила? ПМСМ такого варианта не может быть.
решение "б"
Аватара пользователя
demimurych
Сообщения: 20
Зарегистрирован: 2016.06.27, 01:58

Re: Url Rules. Оптимизация

Сообщение demimurych »

SiZE писал(а):
demimurych писал(а): Путь второй - погрузиться в ад с динамическим добавлением только нужных нам в текущий момент правил.
URL динамически сопоставляется с правилами. Как ты собираешься заранее угадывать нужные правила? ПМСМ такого варианта не может быть.
а) У нас есть УРЛ
б) и мы знаем как работает наш проект

Этой информации более чем достаточно для реализации алгоритма добавления только нужных нам правил в urlmanager
Аватара пользователя
demimurych
Сообщения: 20
Зарегистрирован: 2016.06.27, 01:58

Re: Url Rules. Оптимизация

Сообщение demimurych »

zelenin писал(а):в решении "а" разве не об этом?
В целом да. Вы правы. Одно и тоже разными словами.
Разве что с парой ремарок
1) это то что текущая реализация группировок в yii2 поможет нам ускорить работу, но не избавит нас от перерасхода памяти
2) насколько я понял логику разработчиков yii2, и я с ними согласен, столкнувшись с ситуацией большого количества правил нужно реализовать свой класс работы с правилами ориентированный на условия нашего проекта, а не полагаться на текущие реализации UrlRule и GroupUrlRule. Весь инструментарий для этого в yii2 есть.
Ответить