Skip to content

パフォーマンス最適化

ストアの表示が遅い、管理画面が重い。原因は回線でもサーバースペックでもないことがほとんどです。

どこで時間を食っているか

犯人は PHP のセッションファイルロックです。

Web サーバーは単一スレッドで PHP を動かしているわけではなく、複数のワーカープロセスが同時にリクエストを処理します。ブラウザはページを開くと、そこで参照されるリソースを並列にダウンロードするため、1 人のユーザーが一瞬で複数の同時リクエストを発生させます。

ところが session_start() は、前のリクエストのスクリプトが session_write_close() で解放するまでブロックします。Linux では flock() で実装されています。

結果として、本来並列に処理できたリクエストがセッションロックによって一列に並ばされます。ページ内のリソースが多いほど、体感が悪くなります。

ロック自体は必要なものです。無ければ複数プロセスが同じセッションを同時に読み書きして上書きし合い、ログイン状態が突然消えてしまいます。問題はロックがあることではなく、その媒体がファイルであることです。

解決策:セッションを Redis に移す

3 ステップで、効果はすぐに体感できます。

1. Redis を導入する

宝塔:ソフトウェアストアredis を検索 → インストール。

それ以外の環境では、各ディストリビューションの方法で導入してください。

2. PHP の redis 拡張を導入する

宝塔:ソフトウェアストア → 使用中の PHP バージョン → 設定拡張のインストールredis

3. セッションの保存先を Redis にする

宝塔: PHP の設定 → セッション設定 → 保存方式を redis に変更 → 保存。

パネルなし: php.ini を編集します。

ini
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379"

; Redis にパスワードを設定している場合は、上の行の代わりにこちら
; session.save_path = "tcp://127.0.0.1:6379?auth=あなたのredisパスワード"

PHP を再起動してストアを開いてください。違いははっきり分かります。

Docker を使っている場合

イメージには Redis が同梱済みで、設定は不要です。最初からセッションは Redis に保存されます。

外部の Redis を使う場合は、コンテナ起動時に -e ACG_REDIS_HOST=接続先 を追加してください(Docker でインストール参照)。

共用レンタルサーバーの場合

残念ながら、共用サーバーでは通常 Redis を導入できず php.ini も編集できないため、この最適化は使えません。

プログラムがセッションに Redis を必須としなかったのは、まさに共用サーバーでも動くようにするためです。機能に影響はなく、速くできないだけです。

もう 1 つの落とし穴:設定キャッシュ

ある設定キーがデータベースに存在しない場合、プログラムはリクエストのたびにデータベースへ問い合わせ、排他ロックを取ります。CIFS のようなネットワークマウント上では、これがサイト全体を直列化します。セッションロックよりも深刻です。

症状はサイト全体が理由もなく遅くなることです。その場合は runtime/config が壊れていないか確認してください。

runtime/config を手で削除しないでください。 サイトが壊れます。テンプレートキャッシュを消すときは runtime/view/compile だけにしてください。

その他にできること

対策効果
opcache を有効にするPHP が毎回コンパイルし直さなくなり、明確に速くなります
静的リソースを CDN に載せるただし実 IP の取得方式を正しく設定しないと、全訪問者が CDN の IP に見えます
古い注文を定期的に整理する注文テーブルが巨大だと管理画面の一覧が遅くなります

MIT ライセンスで公開