概念是這樣的,前篇寫到 Zephir 可以很快的搞出一個 php extension,而我挺喜歡用 YII Framework,目前對 YII2 有興趣,雖然 YII 不慢,但純 PHP 的 Framework 效能其實測出來的反應速度都不怎麼樣啦,於是我就想說能否把部分類別取代掉來提速。
因此我建立了一個專案叫 BoostYii,此專案只有實作了一個類別叫 Object,這個類別是和 YII2 的 Object 類別是等效的,但我只有實做一半功能,因為某些功能太複雜了我就放棄,而為了保持相容性,我也另外寫了個 BoostYiiLoader.php 會判斷是否有 boostyii extension,只要在 index.php 中載入這個 Loader 就行了,不用改任何 Code 或 Yii2 Core Framework 即可得到效能的提升。
安裝方法介紹
首先 OS 內要有 zephir,若您是 CentOS 用戶可以參考我寫的前篇來安裝,其他的可以參考官方網站的說明,然後用 git 下載專案回來用 zephir 編譯,命令如下
git clone https://github.com/pigochu/zephir-boost-yii.git cd zephir-boost-yii/extension-src zephir build
如果順利安裝成功,會看到
Compiling... Installing... Extension installed! Don't forget to restart your web server
接著,要新增一行 extension=boostyii.so 於 php.ini 或 /etc/php.d 建立 z-boostyii.ini 自己加進去。
上述 z-boostyii.ini 的命名是因為這個 boostyii.so 不可以比 json.so 先載入,否則會發生錯誤,所以用個 "z-" 的前綴就行了。
然後可以下命令看看是否有載入
php --re boostyii Extension [ <persistent> extension #56 boostyii version 0.0.1 ] { - Classes [3] { Interface [ <internal:boostyii> interface boostyii\base\Arrayable ] { - Constants [0] { } - Static properties [0] { } - Static methods [0] { } - Properties [0] { } - Methods [1] { Method [ <internal:boostyii> abstract public method toArray ] { } } }
如果有正常載入,你可以重新啟動 php-fpm 或 web server 就可以於 yii2 web 使用了。
使用方法介紹
將 php-src 這個文件夾複製到 YII2 的專案,並且你可以改變這個文件夾名稱,然後於 index.php 中 include BoostYiiLoader.php 即可,如下範例為預設的 index.php 然後加上一行而已 :
<?php // comment out the following two lines when deployed to production defined('YII_DEBUG') or define('YII_DEBUG', true); defined('YII_ENV') or define('YII_ENV', 'dev'); require(__DIR__ . '/../vendor/autoload.php'); require(__DIR__ . '/../vendor/yiisoft/yii2/yii/Yii.php'); ## 只要增加這行就可以提速了!! 會不會太屌了啊@@ require(__DIR__ . '/../boostyii/BoostYiiLoader.php'); $config = require(__DIR__ . '/../config/web.php'); $application = new yii\web\Application($config); $application->run();
就是這麼簡單啦 !!
效能測試
我用上述的使用方法建立了 index-boost.php 來和預設的 index.php 比較效能,我的環境如下
- OS : CentOS 6.5 64bit
- PHP 5.4.24 with APC
- CPU INTEL Core2 E6750
以 ab 測試數據如下
ab -c 10 -t 10 http://localhost/boostyii/index.php Document Path: /boostyii/index.php Document Length:11208 bytes Concurrency Level: 10 Time taken for tests: 10.000 seconds Complete requests: 2336 Failed requests:0 Write errors: 0 Total transferred: 27447386 bytes HTML transferred: 26190080 bytes Requests per second:233.60 [#/sec] (mean) Time per request: 42.809 [ms] (mean) Time per request: 4.281 [ms] (mean, across all concurrent requests) Transfer rate: 2680.37 [Kbytes/sec] received ab -c 10 -t 10 http://localhost/boostyii/index-boost.php Document Path: /boostyii/index-boost.php Document Length:11244 bytes Concurrency Level: 10 Time taken for tests: 10.002 seconds Complete requests: 2545 Failed requests:0 Write errors: 0 Total transferred: 29993920 bytes HTML transferred: 28624172 bytes Requests per second:254.44 [#/sec] (mean) Time per request: 39.302 [ms] (mean) Time per request: 3.930 [ms] (mean, across all concurrent requests) Transfer rate: 2928.40 [Kbytes/sec] received
這太扯了,竟然有 9% 的速度提升啊,我才去實作半個 Object 就有如此的效能改善,zephir 真是神器啊。
結語
採用上述方法提速所增加的一行 Code 其實拿去到沒有安裝 boostyii extension 的機器也是可以跑的,因為 Loader 本身會判斷是否有該 extension 然後才載入另外寫的 Object 類別,如果要更複雜些,用 spl_autoloader 來做 lazy loading 都行。
其實這個專案真的寫好玩的,我並不會真的繼續去發展 boostyii,只是要證明用我的方法,可以做到不影響相容性就可以提升 Yii2 的速度,相對的其他的純 PHP Framework 都可以如法炮製,只要先由最基底的類別去實作部分功能就行了。