我們經常說,對於一個 IO 密集型的應用過來說,語言不是效能的瓶頸,IO 的操作纔是效能的瓶頸。我們常常看的也是一個介面請求需要多長時間、一次資料庫查詢需要多少時間,我們很少去測試一行程式碼、一個方法呼叫、一次例項化需要多長時間。
因為我們的專案中,我們大規模的使用了反射 API,我就好奇在 PHP 中一次反射需要多長時間。於是,我們來寫程式碼來測試一下:
class Test {} $startTime = microtime(true); new ReflectionClass(Test::class); $endTime = microtime(true); var_dump(($endTime - $startTime) * 1000);
這不是一次很嚴謹的基準測試,所以我就不執行一萬、百萬次了,就執行一次。結果是 0.0040531158447265625 毫秒。是不是非常快,那麼是不是說我們在專案中可以隨意使用反射 API 了呢?反正,相比一次資料庫查詢動輒幾十幾百甚至幾秒來說,這簡直不值一提。
我們再來看下面這段程式碼的測試:
include 'vendor/autoload.php'; $startTime = microtime(true); new ReflectionClass(Bean::class); $endTime = microtime(true); var_dump(($endTime - $startTime) * 1000);
你猜同樣是構建 ReflectionClass ,區別只是我加入了 Composer 的 Autoload 機制而已。列印的結果竟然是: 0.9691715240478516, 將近 1 毫秒,天啊!這是為什麼呢?因為 PHP 的自動載入機制,在每例項化一個類的時候都會觸發檔案系統中去根據路徑查詢檔案,也就是說可能會有一次 IO 操作。所以,本質上,這不是反射 API 慢,而是自動載入機制慢,是 IO 操作慢,不信你可以把程式碼換一下,輸出的結果也是類似的:
include 'vendor/autoload.php'; $startTime = microtime(true); (new Bean); $endTime = microtime(true); var_dump(($endTime - $startTime) * 1000);
所以,在進行 PHP 專案部署的時候要做好最佳化工作,不然你的介面從語言層面來說就會慢幾十毫秒…… 下面是一些基礎的最佳化:
composer dump-autoload --optimize composer install --no-dev --prefer-dist --prefer-stable php artisan optimize