PHP Profi

Тестируем маршрутизатор Symfony 4.1 Перевод

php route symfony 4.1

Насколько быстрее новый маршрутизатор Symfony в реальных приложениях?

Мы провели несколько тестов, чтобы выяснить это.

Улучшенный маршрутизатор

Несколько дней назад мы получили фантастические новости, что маршрутизатор в Symfony был значительно улучшен. Конечно, мы хотели увидеть как изменения влияют на наше приложение, поэтому мы решили протестировать его на наших собственных роутах.

Если вы пропустили эту новость, вы можете почитать официальный анонс.

Если вы хотите знать, как новый маршрутизатор работает, почитайте пост Nicolas Grekas, где он более подробно описывает новые изменения.

Наши реалии

  • Версия PHP: 7.1.13
  • Статические маршруты: 285
  • Динамические маршруты: 350

Процесс тестирования

Сам процесс довольно прост. Поскольку производительность поиска совпадений зависит от количества настроенных маршрутов(роутов), которые мы имеем, поэтому нам нужно протестировать первый маршрут, несколько случайных маршрутов и последний маршрут, чтобы получить реалистичный тест. Мы сделали это для статических и динамических маршрутов.

class RouteTestCommand extends BaseCommand
{
    const NR_OF_MATCHES = 50000;
    protected static $defaultName = 'route:test';
    private $router;

    public function __construct(RouterInterface $router)
    {
        parent::__construct();
        $this->router = $router;
    }
    
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $output->writeln('First static route: '.$this->matchRoutes(['/admin/statistics/index']));        
        // Add random/last static routes..

        $output->writeln('First dynamic route: '.$this->matchRoutes(['/admin/statistics/3aa63971-1f61-4b28-bd60-5bb1c9582c8a/show']));
        // Add random/last dynamic routes..
        
        $output->writeln('Not Found: '.$this->matchRoutes(['/foo/bar/baz']));
    }

    private function matchRoutes(array $routes): float
    {
        $startTime = microtime(true);
        foreach ($routes as $route) {
            for ($i = 0; $i < self::NR_OF_MATCHES; ++$i) {
                $this->router->match($route);
            }
        }
        $time = microtime(true) - $startTime;

        return number_format(1000 * $time / count($routes), 2);
    }
}

В symfony 3.4

В symfony 3.4 поиск совпадений перебирает все/большинство настроенных маршрутов и пробует найти маршрут для переданного URL-адреса. Есть некоторые оптимизации, такие как нахождение группы маршрутов, которые имеют одинаковый статический префикс, а затем поиск маршрута в этом подмножестве. Попытка сопоставить URL-адрес, который находится в конце списка, приведет к увеличению времени поиска из-за количества произведённых сравнений.

Именно поэтому наши тесты по случайному маршруту, а последний маршрут занимает значительно больше времени, чем матч первого маршрута. Поиск маршрутов, которые не были найдены, займет наибольшее количество времени, так как все настроенные маршруты должны быть проверены, прежде чем сделать вывод о том, что наш маршрут не существует.

В symfony 4.1

Вместо того, чтобы делать отдельные сравнения или вызывать preg_match() для каждого маршрута, он сочетает в себе все регулярные выражения в одно регулярное выражение. Это означает, что мы должны вызвать preg_match() только один раз. И это самый важный фактор для быстрого поиска.

Если вы хотите больше узнать об оптимизации регулярных выражений, почитайте вторую часть поста от Nicolas Grekas.

Результаты

Таблица ниже показывает сколько времени потребовалось, чтобы найти соответствие заданным маршрутам 50.000 раз.

Колонка Diff показывает, насколько быстрее новый маршрутизатор Symfony, по сравнению с нашим нынешним (3.4).

Routes. 3.4 4.1 (7d29a4d) Diff
First static route 448 ms 382 ms -17%
Random static route 1621 ms 474 ms -242%
Last static route 1826 ms 544 ms -234%
       
First dynamic route 746 ms 527 ms -41%
Random dynamic route 1454 ms 531 ms -174%
Last dynamic route 2039 ms 524 ms -289%
       
Not Found 2112 ms 522 ms -304%

Как мы видим, все наши маршруты были найдены быстрее, чем раньше. Особенно заметен прирост скорости на случайном, последнем и когда маршрут не был найден.

Мы довольны этими результатами, так как единственное, что нам нужно сделать, когда зарелизимся - это запустить composer update.

Помните, что это наши результаты на нашем приложении. Ваши результаты, вероятно, не будет такими же, так как производительность сильно зависит от количества маршрутов в вашем приложении и от структуры дерева маршрутов.

ЗЫ: Если кто-нибудь пробовал или уже переключился на своих реальных проектах на новую маршрутизацию, поделитесь впечатлениями и желательно цифрами.

2018-03-15 alek13 оригинал

Последние посты

Комментарии

авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий