改善 PHP 測試階段的效能
測試是最重要,但同時也是最花時間的任務,這篇文章將會說明程式測試可以改善效能的方法。
預計看完本篇文章後,可以改善的部分為:
- 本機跑測試的時間。
- 執行 CI 的時間(參考 Continuous Integration,我們應該要建立 Private Build,因此這件事與第一點是相同的),而 CI 可能又會跟 CD 有關係,也就是可以間接加速交付產品,或是修復錯誤(降低 MTTR)的時間。
- 採用短期分支(原文 Short-Lived Feature Branches)通常會在合併前進行測試與程式碼審查(Code Review),以確保合併後的結果是正確的,因此也能間接加速 PR review 時間。
Code Sniffer 檢查調整參數
檢查指令可能原本是:
vendor/bin/phpcs |
可以改成:
php -d xdebug.mode=off vendor/bin/phpcs --parallel=$(getconf _NPROCESSORS_ONLN) |
調整主要有兩個地方:
- 透過
-d xdebug.mode=off
將 xdebug 功能關掉就能加速,但在執行 phpcs 的情境下加速有限(參數詳細可參考 Xdebug 官方說明) - 透過
--parallel
參數讓檢查能夠並發處理,其中$(getconf _NPROCESSORS_ONLN)
可以取得 CPU 的核心數,例如 Macbook M2 有 8 核,「理論上」有幾核就能快幾倍。
以使用 Macbook M1 Pro 10 核實測檢查 1588 個檔案,結果如下:
- 沒加 parallel 參數 => 159s
- –parallel=8 => 24s
- –parallel=10 => 22s
- xdebug.mod=off + –parallel=10 => 20s
以最快的 20s 來算的話,省下約 87% 的時間。
目前只有試過
squizlabs/php_codesniffer
,friendsofphp/php-cs-fixer
和laravel/pint
沒試過,但原理是一樣的,應該會有效。
Code Sniffer 本機開發檢查調整
以上是可以同時用在本機開發與 CI 的方法,再來下面是適用在本機開發的方法:
phpcs 支援檢查單一個檔案:
vendor/bin/phpcs app/Foo.php app/Bar.php |
如果把新增或修改的檔案透過 git add
加入 stage 後,可以使用下面這個指令找到:
git add app/Foo.php app/Bar.php |
因此可以把這兩個指令組合在一起,就可以只測「有 git add 的變更檔案」:
vendor/bin/phpcs $(git diff --cached --name-only --diff-filter=ACM | grep -e '.php$') |
最後再跟前面的指令組合起來:
php -d xdebug.mode=off vendor/bin/phpcs --parallel=$(getconf _NPROCESSORS_ONLN) $(git diff --cached --name-only --diff-filter=ACM | grep -e '.php$') |
要注意的是,這可能只能在本機搭配 git add
使用,另外 grep 的條件可能會需要客製化。
單元測試調整參數
原本可能是這樣測試的:
vendor/bin/phpunit |
如果沒有要產 coverage 報表的話,可以把 xdebug 關掉:
php -d xdebug.mode=off vendor/bin/phpunit |
實測過的經驗,可以從 345s 縮短到 85s,約省了 75% 的時間。
單元測試控制變數的生命週期
執行測試的過程,如果有使用物件屬性保存資源的話,需要正常回收資源,不然記憶體會用盡(Memory Leak),同時效能也會有一點點差異。
class ApiTest extends TestCase |
以之前的調整經驗,可以從 133s 減到 126s,省約 5% 的時間,雖然省下的時間不多,但可以省非常多記憶體。
省記憶體的另一個角度是有更多記憶體可以做並行測試,因此對加快測試速度還是有幫助的。
Laravel 單元測試控制連線
如果有發現單純執行 php artisan
會連資料庫的話,必須要找出原因在哪,因為這代表每個測試案例在 bootstrap Application 都會連線資料庫,即便該測試案例不需要使用資料庫。
之前曾調整連 Redis 的機制,調整之前 145s ,調整之後 120s,省下 17% 的時間。
寫在最後
還有其他方法可以再加快速度,但程式就需要做更複雜的調整。 只是要回過頭來思考,這一切都是為了讓開發或交付更加快速,以及效率更加快速。(可以參考單元測試文章提到的頻率指標)
如果只是調整參數或程式就能加速測試的話,這 CP 值也實在是太高了,建議大家可以多多嘗試看看。