コードをプロファイリングしてボトルネックを特定する
Hoare の格言は、時期尚早の最適化は諸悪の根源であると述べています。これは、Web サイトをより高速にしようとするときに心に留めておくべき重要なことです。コードを変更する前に、何が原因で速度が低下しているかを判断する必要があります。問題がデータベース関連またはネットワーク関連である可能性がある場合は、このガイドや PHP の最適化に関する他の多くのガイドを参照してください。PHP コードをプロファイリングすることで、ボトルネックの特定を試みることができます。
PHP のバージョンをアップグレードする
PHP エンジンを保守する開発者チームは、何年にもわたって多くの大幅なパフォーマンスの改善を行ってきました。Web サーバーがまだ PHP 3 や PHP 4 などの古いバージョンを実行している場合は、コードの最適化を試みる前に、アップグレードについて調査することをお勧めします。
キャッシュを使用する
Memcache などのキャッシング モジュール、または Smarty などのキャッシングをサポートするテンプレート システムを利用すると、データベースの結果とレンダリングされたページをキャッシュすることで、Web サイトのパフォーマンスを向上させることができます。
出力バッファリングを使用する
PHP はメモリ バッファを使用して、スクリプトが出力しようとするすべてのデータを格納します。このバッファーにより、ユーザーはデータを送信する前にバッファーがいっぱいになるまで待たなければならないため、ページが遅く見える可能性があります。幸いなことに、PHP が出力バッファーをより早く、より頻繁にフラッシュするように強制するいくつかの変更を加えることができます。これにより、ユーザーがサイトをより高速に感じられるようになります。
素朴なセッターとゲッターを書かないようにする
PHP でクラスを作成する場合、単純なセッターやゲッターを作成するのではなく、オブジェクト プロパティを直接操作することで、時間を節約し、スクリプトを高速化できます。次の例では、dog クラスはsetName()
およびgetName()
メソッドを使用して name プロパティにアクセスします。
class dog {
public $name = '';
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
とはそれぞれ name プロパティを格納して返すだけであることに注意しsetName()
てください。getName()
$rover = new dog();
$rover->setName('rover');
echo $rover->getName();
name プロパティを直接設定して呼び出すと、最大 100% 高速に実行でき、開発時間を短縮できます。
$rover = new dog();
$rover->name = 'rover';
echo $rover->name;
理由もなく変数をコピーしない
PHP の初心者は、定義済みの変数を短い名前の変数にコピーしてから作業することで、コードを「よりクリーン」にしようとすることがあります。これが実際にもたらすのは、(変数が変更されたとき) メモリ消費量が 2 倍になるため、スクリプトが遅くなるということです。次の例では、ユーザーが 512KB 相当の文字をテキストエリア フィールドに挿入したとします。この実装では、約 1MB のメモリが使用されることになります。
$description = strip_tags($_POST['description']);
echo $description;
上記の変数をコピーする理由はありません。この操作をインラインで行うだけで、余分なメモリの消費を避けることができます。
echo strip_tags($_POST['description']);
ループ内で SQL クエリを実行しない
よくある間違いは、ループ内に SQL クエリを配置することです。これにより、データベースへのラウンドトリップが複数回発生し、スクリプトが大幅に遅くなります。以下の例では、ループを変更して単一の SQL クエリを作成し、すべてのユーザーを一度に挿入できます。
foreach ($userList as $user) {
$query = 'INSERT INTO users (first_name,last_name) VALUES("' . $user['first_name'] . '", "' . $user['last_name'] . '")';
mysql_query($query);
}
プロデュース:
INSERT INTO users (first_name,last_name) VALUES("John", "Doe")
ループを使用する代わりに、データを 1 つのデータベース クエリに結合できます。
$userData = array();
foreach ($userList as $user) {
$userData[] = '("' . $user['first_name'] . '", "' . $user['last_name'] . '")';
}
$query = 'INSERT INTO users (first_name,last_name) VALUES' . implode(',', $userData);
mysql_query($query);
プロデュース:
INSERT INTO users (first_name,last_name) VALUES("John", "Doe"),("Jane", "Doe")...
最適化を扱うときの良いアプローチSQL
は、必要なフィールドのみを選択することです。すべてのフィールドを選択するのではありません。これはほとんどの場合、特にフィールドがBLOB
の場合、パフォーマンスに大きな影響を与えます。また、インデックス作成も非常に重要ですが、適切に作成した場合に限ります。LIMIT
結果をすぐに表示する必要がない場合は、クエリで節を使用することもお勧めします。
JavaScriptコードの最適化についてはこちら、 Web グラフィックの最適化についてはこちらをご覧ください。