PHP7.4已經發布,釋出了很多新特性,其中有一項功能比較吸引人,那就是預載入功能,可以將檔案提前載入到記憶體當中,據說可以提升PHP效能,但是究竟是不是能提升,能提升多少,我們可以做一個實驗來測試下。
先上github地址 https://github.com/linkkong/php7.4-preload-test
思路
預載入的原理就是將類提前載入到記憶體中,這種提升在fpm場景下最適合,所以筆者做了以下幾個角度的測試。
- 速度測試:比較php7.4預載入、php7.4無預載入、php7.3三種環境下,同一份檔案訪問的表現
- 空間測試:也就是上面三種環境下記憶體使用情況
- CPU使用的情況可以忽略,因為下面的測試使用了docker,已經將cpu使用率降低到了25%
工具
-
php專案:
1) 在www目錄下面,預設訪問的是index.php檔案,裡面引用了www/Dog目錄下的三個檔案(增加檔案讀取操作);
2) 為了驗證預載入確實讀取類到了記憶體中,增加了dog類 -
使用docker-compose編排了三個php環境分別是php7.4預編譯、php7.4普通、php7.3普通
php74: image: php:7.4-fpm volumes: - ./www/:/var/www/html/:cached - ./php/preload.ini:/usr/local/etc/php/conf.d/preload.ini expose: - 9000 deploy: resources: limits: cpus: '0.25' memory: 150M php741: image: php:7.4-fpm volumes: - ./www/:/var/www/html/:cached expose: - 9000 deploy: resources: limits: cpus: '0.25' memory: 150M php73: image: php:7.3.9-fpm volumes: - ./www/:/var/www/html/:cached expose: - 9000 deploy: resources: limits: cpus: '0.25' memory: 150M
預載入比普通多了一個預載入的配置檔案,把www/Dog裡的檔案進行了opcache_compile_file
參考php/preload.ini和www/preload.php
-
增加nginx配置,參考nginx/conf.d/default.conf
環境 Host php7.4預載入 http://localhost:8000/ php7.4無載入 http://localhost:8001/ php7.3普通 http://localhost:8002/
測試
開啟2個視窗,分別執行下面的命令,不要關閉
//監控docker容器的cpu使用和記憶體使用
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
//啟動所有容器,必須使用--compatibility引數,否則CPU記憶體限制無效
docker-compose --compatibility up
執行起環境後可以看到,php74_1是預載入環境,php741_1是無預載入環境,php73_1是php7.3環境,php7.4預載入環境已經比無預載入環境多使用了0.08Mib記憶體,至於是不是已經預載入了類,還不能下結論
下面採用ab來進行簡單的壓測,並用每秒請求數來進行對比
ab -c 10 -n 1000 http://localhost:8000/
測試index.php
測試7.4預載入、7.4無預載入、7.3三種環境的表現
環境和地址 | 第1次 | 第2次 | 第3次 | 第4次 | 第5次 |
---|---|---|---|---|---|
7.4預載入;http://localhost:8000/ | 268 | 367 | 410 | 345 | 359 |
7.4無預載入;http://localhost:8001/ | 153 | 180 | 160 | 137 | 190 |
7.3;http://localhost:8002/ | 154 | 110 | 126 | 134 | 131 |
測試dog.php
dog.php包含了Dog資料夾下的內容,主要測試dog類,是否已經在記憶體中。用curl訪問即可,或者瀏覽器開啟
環境和地址 | 執行結果 |
---|---|
7.4預載入;http://localhost:8000/dog.php | Cannot declare interface AnimalInterface, because the name is already in use in /var/www/html/dog.php |
7.4無預載入;http://localhost:8001/dog.php | It is runningWang! Wang! |
7.3;http://localhost:8002/dog.php | It is runningWang! Wang! |
測試cat.php
cat.php包含cat類,就是將dog類改了下名字全部放到了cat.php檔案中,減少檔案讀寫;主要測試在檔案讀寫次數一致的情況下程式的表現
環境和地址 | 第1次 | 第2次 | 第3次 | 第4次 | 第5次 |
---|---|---|---|---|---|
7.4預載入;http://localhost:8000/cat.php | 334 | 305 | 337 | 395 | 366 |
7.4無預載入;http://localhost:8001/cat.php | 282 | 201 | 221 | 213 | 269 |
7.3;http://localhost:8002/cat.php | 219 | 247 | 216 | 295 | 254 |
總結
- php7.4開啟預載入,效能確實提升了很多,原因就是大幅度減少了檔案讀取的時間
- 未開啟預載入的情況下,php7.3和php7.4效能差距不大
- php7.4開啟了預載入後,但是並沒有預載入特定檔案(Cat類)效能居然也有提升,原因還不得而知???
- 從第二個測試來看php7.4開啟預載入之後,類確實載入到了記憶體中,這就是提升效率的關鍵,但是在實際專案中,這個特性可能會因為不熟悉特性重複定義類導致專案報錯掛掉(潛在的風險)
- 沒有做關於laravel的測試,因為不想做了,原理差不多
- 在實際應用中,應該對經常使用的類進行熱載入,而不要全部載入,參考下面第二個文獻
最終還是做了Laravel的測試,見圖
laravel專案是6.5版本,只修改了route/web.php,把預設返回值改成了一個json,其他均未修改
貌似php7.4只要開啟preload,不需要配置preload檔案也能加快訪問速度(原理未知,可能是自動快取了,如果是自動快取,那麼後期更新專案就需要重啟fpm,不然會有問題),所以我在www目錄下面放入了一個laravel專案,然後用ab 進行了壓測,壓測結果特別低是因為對容器的CPU和記憶體做了限制。
從2,3圖來看,沒有開啟preload的php7.4與php7.3效能相差無幾,但是開啟了preload的php7.4,提升還是很明顯的,降低了非常多的檔案讀取效能消耗
Laravel第二次測試
經過韓天峰大佬指正,php7.3和php7.4也應該同時開啟opcache,上面的實驗提升很大其實是opcache的功勞。
對laravel的vendor/laravel檔案進行了preload,再次做了實驗,得到如上的資料,相比較兩個php7.4是否開啟preload還是有差距的,但是php7.3+opcache的實驗資料居然跟php7.4+preload效能接近,這個還有點想不通,需要進一步測試。也可能是laravel框架和php7.4並不適配,亦或是opcache開啟的引數沒有調優;
存在的問題
- php7.3+opcache的實驗資料居然跟php7.4+preload效能接近
可以改進的地方
- fpm容器沒有調優,沒有設定fpm連線數等
- opcache引數沒有調優,只有 opcache.enable = 1;opcache.enable_cli = 1
- 沒有測試資料庫連結等場景,也沒有評測其他框架
最後
php7.4開啟preload的效能依據官方評測,提升在10%左右,其實並不是很大了,相對開啟opcache,收益較小,而且還跟快取的檔案有關。所以這個實驗也證明了,php7以上的版本,請務必開啟opcache,因為帶來的提升真的很大。
參考文獻
- Composer: How it should preload in PHP 7.4
- 國外同行做的測試,可能是基於laravel
- Preloading in PHP 7.4
- 在 Docker Compose file 3 下限制 CPU 與 Memory
本作品採用《CC 協議》,轉載必須註明作者和本文連結