【轉-來自鳥哥】關於 PHP 的編譯和執行分離

這是來自 @雪候鳥 博客的文章,內容如下:
關於讓”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 同學, 在這件事情上的推動, 呵呵

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章