PHP路由控制器性能测试
前言
前段时间抽空写了个微型路由控制器可以在我的另一篇文章里面看到详细的介绍。虽然在设计的时候及尽量避开了正则匹配和数组循环这种耗时的操作。尽量节省时间。但是那都是理论上的。今天就实际测试了一下。
代码
github上面专门有一个叫做php-router-benchmark的仓库,用来测试路由分发的性能。
上门有测试php-r3,Pux,FastRoute,Symfony2 Dumped,Symfony2 以及Aura v2这几个路由控制器的性能,总体来说R3和FastRoute在最坏的情况下表现最好。其中R3和Pux是C语言实现的插件,有语言上面的性能优势。
测试
首先fork了一份这个benchmark的库,并把自己的Router的测试代码加上去了。同样的测试条件。由于R3没有装上,还有Pux安装失败。所以本次测试仅仅针对FastRoute,Symfony2 Dumped,Symfony2,Aura v2以及Router。
这样也好,反正这几个都是纯PHP实现的。另外两个C语言实现的这次就不进行比较了。
结果
首先是最坏情况下的测试,其中包含了两个测试用例,一个是找不到的404 还有一个是在列表最后一个才能匹配到的,也就是最坏的两种情况。
Worst-case matching
This benchmark matches the last route and unknown route. It generates a randomly prefixed and suffixed route in an attempt to thwart any optimization. 1,000 routes each with 9 arguments.
This benchmark consists of 10 tests. Each test is executed 1,000 times, the results pruned, and then averaged. Values that fall outside of 3 standard deviations of the mean are discarded.
Test Name | Results | Time | + Interval | Change |
---|---|---|---|---|
Router - unknown route (1000 routes) | 993 | 0.0000232719 | +0.0000000000 | baseline |
Router - last route (1000 routes) | 981 | 0.0000955424 | +0.0000722705 | 311% slower |
FastRoute - unknown route (1000 routes) | 990 | 0.0005051955 | +0.0004819236 | 2071% slower |
FastRoute - last route (1000 routes) | 998 | 0.0005567203 | +0.0005334484 | 2292% slower |
Symfony2 Dumped - unknown route (1000 routes) | 998 | 0.0006116139 | +0.0005883420 | 2528% slower |
Symfony2 Dumped - last route (1000 routes) | 998 | 0.0007765370 | +0.0007532651 | 3237% slower |
Symfony2 - unknown route (1000 routes) | 996 | 0.0028456177 | +0.0028223458 | 12128% slower |
Symfony2 - last route (1000 routes) | 993 | 0.0030129542 | +0.0029896823 | 12847% slower |
Aura v2 - last route (1000 routes) | 989 | 0.1707107230 | +0.1706874511 | 733450% slower |
Aura v2 - unknown route (1000 routes) | 988 | 0.1798588730 | +0.1798356011 | 772760% slower |
查看上表的数据,我自己的Router在两种测试用例的最坏情况下都是表现最好的。并且把其他几个远远的甩出几条街。看来这个主要得益于使用树形结构的PHP数组来存储路由表。所以进行遍历的时候始终能达到O(log n)的时间复杂度。
然后再来看最好的情况,也就是在第一个url就能匹配到的情况。
First route matching
This benchmark tests how quickly each router can match the first route. 1,000 routes each with 9 arguments.
This benchmark consists of 5 tests. Each test is executed 1,000 times, the results pruned, and then averaged. Values that fall outside of 3 standard deviations of the mean are discarded.
Test Name | Results | Time | + Interval | Change |
---|---|---|---|---|
FastRoute - first route | 998 | 0.0000498390 | +0.0000000000 | baseline |
Symfony2 Dumped - first route | 995 | 0.0000517531 | +0.0000019141 | 4% slower |
Router - first route | 994 | 0.0001499363 | +0.0001000972 | 201% slower |
Aura v2 - first route | 998 | 0.0008559464 | +0.0008061073 | 1617% slower |
Symfony2 - first route | 998 | 0.0012734995 | +0.0012236604 | 2455% slower |
查看这个表的数据,每一个库只有一个测试用例。是测试的“最好”的情况。这里之所以加上引号是因为,Router使用的是树形结构存储,其他几个库所谓的“最好”情况,其实不适用了。不能在第一个匹配到。所以应该说在这个测试用例中Router还是以比较平均的时间来和其他几个库的最好时间进行比较!!!(比较一下上下两个表中的Time绝对值就能看出,其他几个库在下面的“最好”情况下都比上面的最坏情况要好很多,但是Router库的表现确是相反的,并且不管那种情况时间都是比较接近的,这就和之前提到的树形节点遍历的时间复杂度相对固定有关系)
后记
这次测试了几个纯PHP实现的路由控制器,等下次继续把两个C语言实现的库一起拿来比较一下!!!