https://www.yiiframework.com/doc/guide/2.0/zh-cn/tutorial-performance-tuning
性能優化
有許多因素影響你的 Web 應用程序的性能。有些是環境, 有些是你的代碼,而其他一些與 Yii 本身有關。 在本節中,我們將列舉這些因素並解釋如何通過調整這些因素來提高應用程序的性能。
優化你的 PHP 環境
一個好的 PHP 環境是非常重要的。為了得到最大的性能,
- 使用最新穩定版本的 PHP。 PHP 的主要版本可能帶來顯著的性能提升。
- 啟用字節碼緩存 Opcache(PHP 5.5或更高版本) 或 APC (PHP 5.4或更早版本)。字節碼緩存省去了每次解析和加載 PHP 腳本所帶來的開銷。
- Tune
realpath()
cache.
禁用調試模式
對於運行在生產環境中的應用程序,你應該禁用調試模式。 Yii 中使用名為 YII_DEBUG
的常量來定義調試模式是否應被激活。 若啟用了調試模式,Yii 將需要額外的時間來產生和記錄調試信息。
你可以將下面的代碼行放在 入口腳本 的開頭來禁用調試模式:
defined('YII_DEBUG') or define('YII_DEBUG', false);
提示:
YII_DEBUG
的默認值是 false 。所以如果你確信你不在你應用程序代碼中別的地方更改其默認值, 你可以簡單地刪除上述行來禁用調試模式。
使用緩存技術
你可以使用各種緩存技術來提高應用程序的性能。例如,如果你的應用程序允許用戶以 Markdown 格式輸入文字, 你可以考慮緩存解析后的 Markdown 內容,避免每個請求都重復解析相同的 Markdown 文本。 請參閱 緩存 一節, 了解 Yii 提供的緩存支持。
開啟 Schema 緩存
Schema 緩存是一個特殊的緩存功能, 每當你使用活動記錄時應該要開啟這個緩存功能。如你所知, 活動記錄能智能檢測數據庫對象的集合(例如列名、列類型、約束)而不需要手動地描述它們。 活動記錄是通過執行額外的 SQL 查詢來獲得該信息。 通過啟用 Schema 緩存,檢索到的數據庫對象的集合將被保存在緩存中並在將來的請求中重用。
要開啟 Schema 緩存,需要配置一個 cache
應用組件來儲存 Schema 信息, 並在 配置 中設置 yii\db\Connection::$enableSchemaCache 為 true
:
return [ // ... 'components' => [ // ... 'cache' => [ 'class' => 'yii\caching\FileCache', ], 'db' => [ 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=localhost;dbname=mydatabase', 'username' => 'root', 'password' => '', 'enableSchemaCache' => true, // Duration of schema cache. 'schemaCacheDuration' => 3600, // Name of the cache component used to store schema information 'schemaCache' => 'cache', ], ], ];
合並和壓縮資源文件
一個復雜的網頁往往包括許多 CSS 和 JavaScript 資源文件。 為減少 HTTP 請求的數量和這些資源總下載的大小,應考慮將它們合並成一個單一的文件並壓縮。 這可大大提高頁面加載時間,且減少了服務器負載。 想了解更多細節,請參閱前端資源部分。
優化會話存儲
默認會話數據被存儲在文件中。 這是好的對處於發展項目或小型項目。 但是,當涉及要處理大量並發請求時, 最好使用其他的會話存儲方式,比如數據庫。 Yii 支持各種會話存儲。 你可以通過在配置中配置 session
組件來使用這些存儲, 如下代碼:
return [ // ... 'components' => [ 'session' => [ 'class' => 'yii\web\DbSession', // Set the following if you want to use DB component other than // default 'db'. // 'db' => 'mydb', // To override default session table, set the following // 'sessionTable' => 'my_session', ], ], ];
以上配置是使用數據庫來存儲會話數據。默認情況下, 它會使用 db
應用組件連接數據庫並將會話數據存儲在 session
表。 因此,你必須創建如下的 session
表,
CREATE TABLE session ( id CHAR(40) NOT NULL PRIMARY KEY, expire INTEGER, data BLOB )
你也可以通過使用緩存來存儲會話數據 yii\web\CacheSession 。 理論上講,你可以使用只要支持數據緩存。 但是請注意,某些緩存的存儲當達到存儲限制會清除緩存數據。出於這個原因,你應主要在不存在存儲限制時才使用這些緩存存儲。 如果你的服務器支持 Redis,強烈建議你通過使用 yii\redis\Session 來作為會話存儲。
如果您的服務器上有 Redis, 強烈建議您使用 yii\redis\Session 作為會話存儲。
優化數據庫
執行數據庫查詢並從數據庫中取出數據往往是一個 Web 應用程序主要的性能瓶頸。 盡管使用數據緩存技術可以緩解性能下降,但它並不完全解決這個問題。 當數據庫包含大量的數據且緩存數據是無效的, 獲取最新的數據可能是最耗性能的假如在沒有適當地設計數據庫和查詢條件。
一般來說,提高數據庫查詢的性能是創建索引。例如,如果你需要找一個用戶表的“用戶名”, 你應該為“用戶名”創建一個索引。 注意,盡管索引可以使選擇查詢的速度快得多,但它會減慢插入、更新和刪除的查詢。
對於復雜的數據庫查詢,建議你創建數據庫視圖來保存查詢分析和准備的時間。
最后,在“SELECT”中使用“LIMIT”查詢。 這可以避免從數據庫中取出大量數據。
使用普通數組
盡管活動記錄對象使用起來非常方便, 但當你需要從數據庫中檢索大量數據時它的效率不如使用普通的數組。 在這種情況下,你可以考慮在使用活動記錄查詢數據時調用 asArray()
, 使檢索到的數據被表示為數組而不是笨重的活動記錄對象。例如,
class PostController extends Controller { public function actionIndex() { $posts = Post::find()->limit(100)->asArray()->all(); return $this->render('index', ['posts' => $posts]); } }
在上述代碼中,$posts 將被表中的行填充形成數組。每一行是一個普通的數組。要訪問 第 i 行的 title
列,你可以使用表達式 $post[$i]['title']
。
你也可以使用 DAO 以數組的方式來構建查詢和檢索數據。
優化 Composer 自動加載
因為 Composer 自動加載用於加載大多數第三方類文件, 應考慮對其進行優化,通過執行以下命令:
composer dumpautoload -o
另外,您可以考慮使用 authoritative class maps 和 APCu 緩存。 請注意,這兩種選擇可能適用於您的特定情況,也可能不適合您。
處理離線數據
當一個請求涉及到一些資源密集操作, 你應該想辦法在無需用戶等待他們完成脫機模式時來執行這些操作。
有兩種方法可以離線數據處理:推和拉。
在拉中,只要有請求涉及到一些復雜的操作,你創建一個任務,並將其保存在永久存儲,例如數據庫。然后, 使用一個單獨的進程(如 cron 作業)拉任務,並進行處理。 這種方法很容易實現,但它也有一些缺點。 例如,該任務過程中需要定期地從任務存儲拉。如果拉頻率太低,這些任務可以延遲處理; 但是如果頻率過高,將引起的高開銷。
在推中,你可以使用消息隊列(如 RabbitMQ ,ActiveMQ , Amazon SQS 等)來管理任務。 每當一個新的任務放在隊列中,它會啟動或者通知任務處理過程去觸發任務處理。
性能分析
你應該配置你的代碼來找出性能缺陷,並相應地采取適當措施。 以下分析工具可能是有用的:
准備擴展應用程序
當沒有任何幫助時,您可以嘗試使您的應用程序可擴展。Configuring a Yii2 Application for an Autoscaling Stack 中提供了一個很好的介紹。有關進一步閱讀,請參閱 Web apps performance and scaling.