效能


Symfony極為之快。當然了,如果你真正需要速度,還有許多能讓你讓Symfony變得更快的方法。本章,你將探索一些方法,讓Symfony程式快上加快。

使用Byte Code快取(如OPcache) 

#改善效能時你應該做的第一件事是使用一種「byte code cache」。這些快取儲存了編譯後的PHP檔案以避免在每次請求時重複編譯它們。

有很多 byte code caches 可以利用,其中的一些還是開源的。截止到PHP 5.5, PHP內建了  OPcache 。舊版中最廣泛使用的byte code cache是​​ APC

使用byte code cache有百利而無一害,Symfony被打造成「可以在這種類型的環境中表現極佳」。

監控原始檔的改變 

多數byte code cache監控著原始檔的改變。這可確保如果檔案原始碼發生改變,byte code將會自動編譯。這非常方便,但有些過載。

因此,一些byte code caches提供了一個選項來關閉這些檢查。例如,要在APC中關閉檢查,直接加入 apc.stat=0 到你的 php.ini 設定檔。

當關閉這些檢查時,將由伺服器管理員來負責「確保快取在任何來源檔案發生變更時被清除」。否則,你的更新將不會在程式中被看到。

同理,byte code快取必須在部署程式時被清除(例如,使用APC時透過呼叫apc_clear_cache() PHP函數,以及,使用Opcache時透過opcache_reset( ))。

在PHP中,命令列以及web進程並沒有共用相同的OPcache。這意味著你不能透過執行終端機中的某些命令來清除web伺服器上的OPcache。你可以重啟伺服器或透過網頁伺服器呼叫 apc_clear_cache()opcache_reset() 函數(如,在執行web腳本時包容它們)。

#

優化全部Symfony使用的檔案 

預設時,PHP的OPcache在byte code快取中存了2000個檔案。這個數字對於一般的Symfony程式來說還是太小,因此你必須設定opcache.max_accelerated_files 設定選項為更高的值:

; php.iniopcache.max_accelerated_files = 20000

設定PHP realpath快取 

PHP使用了一個內部快取來儲存「類別檔案路徑」對應到「檔案系統真實路徑」的結果。這提高了Symfony這種「開啟許多PHP檔案」的程式效能,特別是在Windows平台上。

預設時PHP設定了一個 16Krealpath_cache_size,這對Symfony來說實在太小。將這個值更新到至少 4096K。此外,快取路徑預設時只保存120 秒,同樣考慮透過realpath_cache_ttl 選項來更新此值:

; php.ini
realpath_cache_size=4096K
realpath_cache_ttl=600

使用Composer的類別映射功能 

預設時,Symfony標準版使用的是autoload.php 檔案中的Composer自動載入器(autoloader)。這個載入器很容易使用,因為它會自動尋找任何「你在已註冊目錄中放置了」的新類別。

不幸的是,這有使用成本,因為類別載入器要遍歷全部已配置的命名空間,以便找到一個特定文件,發起file_exists() 的呼叫直到最終找到它想要的文件為止。

最簡單的方案是告訴Composer建立一個最佳化的"class map"(類別映射),這是一個所有類別所在位置的大數組,並且存放在vendor/composer/autoload_classmap. php 中。

這個類別映射可以由命令列生成,可能會成為你部署過程的一部分。

1
#
$  composer dump-autoload --optimize --no-dev --classmap-authoritative
  • --optimize
  • 剝離你程式中的每一個相容PSR-0 和 PSR-4 的類別。
  • --no-dev
  • 排除那些你只在開發環境下使用的類別(如tests)。
  • --classmap-authoritative
  • 可防止Composer在檔案系統中尋找那些沒有出現在類別映射中的類別。

用APC快取Autoloader 

#另一個方案是在類別中首次定位再來快取其位置。 Symfony自帶了一個類別 - ApcClassLoader - 專門用來幹這個。要使用它,只需適配你的前端控制器檔案。如果你使用了標準版框架,可作出以下改變:

// app.php// ... 
use Symfony\Component\ClassLoader\ApcClassLoader; 
$loader = require __DIR__.'/../app/autoload.php';include_once __DIR__.'/../app/bootstrap.php.cache'; 
// Use APC for autoloading to improve performance
// Change 'sf2' by the prefix you want in order
// to prevent key conflict with another application
// 使用APC自动加载以提升性能,改变'sf2'为你希望的前缀,
// 以防止同其他程序发生key冲突$loader = new ApcClassLoader('sf2', $loader);$loader->register(true); 
// ...

更多細節,參考 #對Class Loader進行快取 一文。

當使用APC autoloader時,如果你添加了新類,它們將被自動找到,所有東西的運作一如既往(即,並無必要「清除」快取)。但是,如果你改變了某個特定命名空間或前綴的位置,你就需要flush你的APC快取。否則,自動載入器仍將在那個命名空間的舊位置來尋找所有的類別。

使用Bootstrap檔案 

#為確保彈性最佳化和程式碼重複使用,Symfony程式利用了多樣化的類別和第三方元件。但在每次請求中從分散位置載入全部這些類別會導致一定程度的過載。為減輕負責,Symfony提供了一個腳本來產生一個被稱為 bootstrap file 文件,考慮的是在單一文件中載入多個類別定義。透過包容這個文件 (它包含了各種核心類的拷貝),Symfony不再需要包容任何「含有那些類」的源文件。這將減少不少的硬碟吞吐(disc IO)。

如果你正在使用Symfony標準版,那你應該已經使用了這個bootstrap啟動檔。為確保使用,打開你的前端控制器(通常是app.php),然後檢查以下程式碼行確實存在:

1
include_once __DIR__.'/../var/bootstrap.php.cache';
#

注意,當使用bootstrap檔案時有兩個不利點:

  • 此檔案會在任意原始資源發生改變時重新生成(如,當你更新了Symfony的src程式碼或vendor三方類別庫時);
  • 偵錯時,開發者需要在bootstrap檔案中設定斷點。

如果你使用的是Symfony標準版,啟動檔案會在vendor類別庫更新之後,透過composer install 指令來自動重建(譯註:指composer.json中的post腳本等,也可手動執行)

Bootstrap檔案和Byte Code快取 

即便使用了一個byte code快取,在使用bootstrap檔案時仍會提高效能,這是因為需要監控「發生改變」的檔案變少了。當然這個功能如果在byte code cache中被關閉的話 (即在APC中設定 apc.stat=0),就再無理由使用bootstrap檔。