這是來自 @雪候鳥 博客的文章,內容如下:
關於讓”PHP的編譯和執行分離”這個問題, 一直有人提, 也一直有人嘗試. 提的人認爲編譯執行分離以後, 可以得到性能提升, 可以做代碼保護等.
我本身並不是對這個特性很感冒, 因爲這裏面存在一個投入產出比. 讓我來給大家解釋一下, 然而不管怎麼樣, 在最後我會給大家提供一種方案來實現這個功能.
1. PHP的編譯並不是很耗時
我之前的文章也介紹過, PHP的編譯是線性的編譯過程, 不做任何優化, 所以這個過程非常之快. 而編譯和執行分離這個特性的提出着認爲分離以後, 可以省掉編譯過程, 會有很大的性能提升.
2. 開發速度
PHP的一個優點就是開發/部署/調試非常方案, 更改立即見效, 而如果我們採用了編譯/執行分離以後, 那麼更改就需要首先編譯, 然後部署, 然後才能生效, 這對於開發來說, 並不是什麼好事.
3. 我們有APC/Zend O+等第三方的代碼緩存工具
APC等第三方的代碼緩存工具(Opcodes Cache)已經相對比較成熟, 並對開發者透明, 大家只要在服務器上安裝了APC, 就可以得到編譯/執行分離的性能提升.
當然, 還有一些因素, 比如編譯/執行分離這個方案是有人在做的, 但是還不成熟等等.
最後呢, 我給大家提供一個類似的解決方案.
首先, 我要打個廣告, 以後APC將由我來維護, 大家以後在APC的使用中如果有問題, 可以直接聯繫我.
迴歸正題: 要實現編譯和執行分離, 其實我們藉助APC就能做到, APC提供了一族apc_bin_dump, apc_bin_load函數, 能把Opcodes緩存導出到外部文件中.
然而, 可惜的是, 這部分功能以前一直不能很好的正常工作, 這和之前的開發者因爲時間原因不在投精力在這個上面是有關係的.
經過我對apc_bin系列函數的重新梳理, 修復以後, 這部分功能現在終於可以正常工作了, 那麼基於這些函數, 我們就可以實現編譯執行分離..
思路很簡單, 在本地通過apc_bin_dumpfile把我們的php文件, 導出成bin文件, 然後在服務器上通過apc_bin_loadfile來讀取這些bin文件. 就可以實現編譯和執行分離啦, 一個簡單的示意代碼如下:
$ find ./ -name "*.php" -exec php -r "apc_bin_dumpfile(array('{}'), array(), '{}' . '.bin');" \;
然後在服務器端的文件自動加載部分
<?php
function __autoload($name) {
/*首先計算出文件名字*/
$file = 根據類名得到PHP文件路徑();
if (!file_exists($file)) {
//文件不存在, 說明我們還沒有load過, 那麼創建一個空文件.
file_put_contents($file, '');
apc_bin_loadfile($file . '.bin');
} else {
//我們已經load過了, 理論上應該已經被服務器的APC緩存處理Cache住了.
}
include ($file);
}
當然, 這裏只是一個簡單的示意, 如果要實際使用, 你還要考慮緩存被換出的可能, 那麼一個解決方案就是設置倆個自動加載函數, 第一個如上, 第二個如果被調用, 就說明緩存被換出, 導致include了一個空文件, 於是就再次load一次bin文件就可以了.
當然, 你也可以把所有的文件打包到一個bin文件中, 然後只load一次, 後續就交給服務器上的APC Cache來做就可以了. 但是這裏有一個要注意的點就是,
那麼對於這部分希望代碼保護功能的人來說, 就可以使用APC來免費的完成這些事情了. 不過, 這個方案確實有點醜陋, 後續可以考慮在APC上增加直接對bin文件的支持.
最後, thanks to @cfc4n 同學, 在這件事情上的推動, 呵呵