2 フォロワー

パフォーマンスチューニング

Webアプリケーションのパフォーマンスには、多くの要因が影響します。環境的なもの、コードに関連するもの、Yii自体に関連するものなどがあります。このセクションでは、これらの要因の大部分を列挙し、これらの要因を調整することでアプリケーションのパフォーマンスを向上させる方法を説明します。

PHP環境の最適化

適切に設定されたPHP環境は非常に重要です。最大限のパフォーマンスを得るためには、

  • 最新の安定版PHPバージョンを使用してください。メジャーリリースでは、パフォーマンスが大幅に向上することがあります。
  • Opcache(PHP 5.5以降)またはAPC(PHP 5.4)でバイトコードキャッシングを有効にします。バイトコードキャッシングにより、着信リクエストごとにPHPスクリプトの解析とインクルードに費やされる時間を回避できます。
  • realpath()キャッシュのチューニング.

デバッグモードの無効化

本番環境でアプリケーションを実行する場合は、デバッグモードを無効にする必要があります。Yiiは、YII_DEBUGという名前の定数の値を使用して、デバッグモードを有効にするかどうかを示します。デバッグモードが有効になっている場合、Yiiはデバッグ情報の生成と記録に余分な時間を費やします。

エントリスクリプトの先頭に次のコード行を配置して、デバッグモードを無効にすることができます。

defined('YII_DEBUG') or define('YII_DEBUG', false);

情報:YII_DEBUGのデフォルト値はfalseです。アプリケーションコードの他の場所でデフォルト値を変更していないことが確実な場合は、デバッグモードを無効にするために上記の行を削除するだけで済みます。

キャッシング技術の利用

さまざまなキャッシング技術を使用して、アプリケーションのパフォーマンスを大幅に向上させることができます。たとえば、アプリケーションでユーザーがMarkdown形式でテキストを入力できるようにする場合は、同じMarkdownテキストをリクエストごとに繰り返し解析するのを避けるために、解析されたMarkdownコンテンツをキャッシュすることを検討できます。キャッシングセクションを参照して、Yiiが提供するキャッシングサポートについて学習してください。

スキーマキャッシングの有効化

スキーマキャッシングは、アクティブレコードを使用している場合に有効にする必要がある特別なキャッシング機能です。ご存じのとおり、アクティブレコードは、手動で記述する必要なく、DBテーブルに関するスキーマ情報(例:列名、列の種類、制約)を検出するのに十分なほどインテリジェントです。アクティブレコードは、追加のSQLクエリを実行することでこの情報を取得します。スキーマキャッシングを有効にすると、取得されたスキーマ情報はキャッシュに保存され、今後のリクエストで再利用されます。

スキーマキャッシングを有効にするには、スキーマ情報を格納するアプリケーションコンポーネントとしてcacheを構成し、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',
        ],
    ],
];

アセットの結合と圧縮

複雑なWebページには、多くのCSSおよび/またはJavaScriptアセットファイルが含まれることがよくあります。HTTPリクエストの数とこれらのアセットの全体的なダウンロードサイズを削減するために、それらを1つのファイルに結合して圧縮することを検討する必要があります。これにより、ページの読み込み時間が大幅に向上し、サーバーの負荷が軽減される可能性があります。詳細については、アセットセクションを参照してください。

セッションストレージの最適化

デフォルトでは、セッションデータはファイルに保存されます。実装では、session_write_close()(YiiではYii::$app->session->close()として実行できます)またはリクエストの終了時にセッションが閉じられる時点まで、ファイルをロックしています。セッションファイルがロックされている間、同じセッションを使用しようとしている他のすべてのリクエストはブロックされ、つまり、最初のリクエストがセッションファイルを解放するのを待機します。これは開発やおそらく小規模なプロジェクトには問題ありません。しかし、大量の同時リクエストを処理する場合、データベースなどのより高度なストレージを使用する方が良いでしょう。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を使用してセッションストレージとして使用することを強くお勧めします。

データベースの最適化

DBクエリの実行とデータベースからのデータの取得は、Webアプリケーションにおける主要なパフォーマンスボトルネックとなることがよくあります。データキャッシング技術を使用するとパフォーマンスの低下を軽減できますが、問題を完全に解決するわけではありません。データベースに膨大な量のデータが含まれており、キャッシュされたデータが無効な場合、適切なデータベースとクエリの設計なしでは、最新のデータを取得することが非常にコストがかかる可能性があります。

DBクエリの性能を向上させる一般的な手法は、フィルタリングする必要があるテーブル列にインデックスを作成することです。たとえば、usernameでユーザーレコードを検索する必要がある場合、usernameにインデックスを作成する必要があります。インデックスを作成するとSELECTクエリを大幅に高速化できますが、INSERT、UPDATE、DELETEクエリは遅くなることに注意してください。

複雑なDBクエリの場合、クエリの解析と準備時間を節約するためにデータベースビューを作成することをお勧めします。

最後に、SELECTクエリでLIMITを使用してください。これにより、データベースから膨大な量のデータを取得して、PHPに割り当てられたメモリを使い果たすことがなくなります。

プレーン配列の使用

アクティブレコードは非常に便利ですが、データベースから大量のデータを取得する必要がある場合、プレーン配列を使用するほど効率的ではありません。この場合、データを取得したときにアクティブレコードを使用してasArray()を呼び出すことを検討して、取得したデータがかさばるアクティブレコードオブジェクトではなく配列として表現されるようにすることができます。たとえば、

class PostController extends Controller
{
    public function actionIndex()
    {
        $posts = Post::find()->limit(100)->asArray()->all();
        
        return $this->render('index', ['posts' => $posts]);
    }
}

上記のコードでは、$postsはテーブル行の配列として設定されます。各行はプレーン配列です。i番目の行のtitle列にアクセスするには、$posts[$i]['title']という式を使用できます。

プレーン配列でクエリを構築し、データを取得するには、DAOを使用することもできます。

Composerオートローダーの最適化

Composerオートローダーは、ほとんどのサードパーティのクラスファイルを含めるために使用されるため、次のコマンドを実行して最適化することを検討する必要があります。

composer dumpautoload -o

さらに、権威的なクラスマップAPCuキャッシュの使用を検討できます。どちらの最適化も、特定のケースに適しているとは限りません。

オフラインでのデータ処理

リクエストにリソースを大量に消費する操作が含まれる場合、ユーザーに終了を待たせることなく、オフラインモードでそれらの操作を実行する方法を検討する必要があります。

データはプル方式とプッシュ方式の2つの方法でオフラインで処理できます。

プル方式では、リクエストに複雑な操作が含まれるたびに、タスクを作成してデータベースなどの永続ストレージに保存します。次に、別のプロセス(cronジョブなど)を使用してタスクを取得し、処理します。この方法は実装が容易ですが、いくつかの欠点があります。たとえば、タスクプロセスは定期的にタスクストレージからプルする必要があります。プル頻度が低すぎると、タスクの処理が大幅に遅れる可能性がありますが、頻度が高すぎると、高いオーバーヘッドが発生します。

プッシュ方式では、メッセージキュー(RabbitMQ、ActiveMQ、Amazon SQSなど)を使用してタスクを管理します。新しいタスクがキューに追加されると、タスク処理プロセスが開始または通知されて、タスク処理がトリガーされます。

パフォーマンスプロファイリング

コードをプロファイリングしてパフォーマンスのボトルネックを特定し、それに応じて適切な対策を講じる必要があります。次のプロファイリングツールが役立つ場合があります。

スケーリングのためのアプリケーションの準備

何も効果がない場合は、アプリケーションをスケーラブルにすることができます。Yii 2アプリケーションを自動スケーリングスタック用に構成するで、良い紹介が提供されています。

タイプミスを見つけたり、このページの改善が必要だと考えますか?
GitHubで編集する !