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語言實現的庫一起拿來比較一下!!!