php symfony urlmatcher->match,Symfony 4.1:最快的PHP路由

依照独立跑分,Symfony 4 是 最快的框架,但我们持续努力令其更快。在 Symfony 4.1 中,我们改进了 Routing组件 让它在匹配到到访URL时变得更快。

在web程序中,路由被切分为两个主要的动作: generation(生成),根据给定的路由及其参数生成URL;以及 matching(匹配),决定哪个PHP代码(即controller)会被执行以作为到访URL的响应。

为了在编译阶段加速程序,Symfony 生成了一个名为 "matcher" 的PHP类,包含全部路由定义,为到访的URL而专门优化。例如,这是一个为 Symfony 演示程序 而生成的码段:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23// var/cache/prod/srcProdDebugProjectContainerUrlMatcher.php

class srcProdDebugProjectContainerUrlMatcher

{

// ...

public function match($rawPathinfo)

{

// ...

// blog_post

if (preg_match('#^/(?P<_locale>en|fr|de|es)/blog/posts/(?P[^/]++)$#s', $pathinfo, $matches)) {

if ('GET' !== $canonicalMethod) {

$allow[] = 'GET';

goto not_blog_post;

}

return $this->mergeDefaults(array_replace($matches, array('_route' => 'blog_post')), array ( '_controller' => 'App\\Controller\\BlogController::postShow', '_locale' => 'en',));

}

not_blog_post:

// ...

}

}

根据以下文章中的点子,在 Symfony 4.1 中我们重构了 matcher 类的生成器: Fast request routing using regular expressions。本来解释了 FastRoute 中使用的技巧,这是由天才的PHP贡献者 Nikita Popov 所写的路由类库。

基本想法是,避免在每一个路由中依次调用 preg_match(),取而代之的是,把全部正则合并为一个单一正则。我们也做了其他大大小小的优化。如果你对此感到好奇,参考 Pull Request #26059 和 #26169 以了解细节。

总之,若以相同的 Symfony 演示程序为例,下面是今日 blog_post 路由如何被匹配到的:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30$regexList = array(

0 => '{^(?'

.'|/(en|fr|de|es)/admin/post/?(*:82)'

.'|/(en|fr|de|es)/admin/post/new(*:166)'

.'|/(en|fr|de|es)/admin/post/(\\d+)(*:253)'

.'|/(en|fr|de|es)/admin/post/(\\d+)/edit(*:345)'

.'|/(en|fr|de|es)/admin/post/([^/]++)/delete(*:442)'

.'|/(en|fr|de|es)/blog/?(*:519)'

.'|/(en|fr|de|es)/blog/rss\\.xml(*:603)'

.'|/(en|fr|de|es)/blog/page/([1-9]\\d*)(*:694)'

.'|/(en|fr|de|es)/blog/posts/([^/]++)(*:784)'

.'|/(en|fr|de|es)/blog/comment/([^/]++)/new(*:880)'

.'|/(en|fr|de|es)/blog/search(*:962)'

.'|/(en|fr|de|es)/login(*:1038)'

.'|/(en|fr|de|es)/logout(*:1116)'

.'|/(en|fr|de|es)?(*:1188)'

.')$}sD',

);

foreach ($regexList as $offset => $regex) {

// ...

default:

$routes = array(

// ...

784 => array(array('_route' => 'blog_post', '_controller' => 'App\\Controller\\BlogController::postShow', '_locale' => 'en'), array('_locale', 'slug'), array('GET' => 0), null),

);

// ...

}

实践中,合并全部正则,把URL匹配时的性能给提高了两个数量级。在我们的基准测试中,Symfony 4.1 URL 匹配能力77倍快 于之前的 Symfony 版本。这也意味着 Symfony 4.1 的路由是最快的PHP路由,打败了 FastRoute 和其他所有 routing libraries(路由类库)。

最强的一点: 你毋须在程序中做任何改变 即可使用这个最快的路由系统。只需在 end of May 2018 发布时升级到 Symfony 4.1 即可。同时你还可以在自己的程序中测试它,并把发现的问题上报。

Update: Nicolas 发布了两篇技术文章来详细解释新 router 是如何运作的:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值