ホームページ >バックエンド開発 >PHPチュートリアル >PHP(RT) の最適化に関する HOWTO

PHP(RT) の最適化に関する HOWTO

WBOY
WBOYオリジナル
2016-06-23 14:31:53839ブラウズ

コピー元:

http://phplens.com/lens/php-book/optimizing-debugging-php.php

著者: PHP の最適化に関する HOWTO がわかりません

PHP は非常に高速ですプログラミング言語ですが、PHP の最適化にはコードの実行速度だけではありません。

この章では、PHP の最適化にコードに関係しない多くの要素が含まれる理由、および PHP のチューニングに PHP のパフォーマンスの関連性を理解する必要がある理由を説明します。サーバー上の他のすべてのサブシステムに影響を及ぼし、これらのサブシステムによって引き起こされるボトルネックを特定して修正します。また、PHP スクリプトをさらに高速に実行できるように調整および最適化する方法についても説明します。

高いパフォーマンスの達成

優れたパフォーマンスについて話すとき、PHP スクリプトの実行速度について話しているのではありません。パフォーマンスは、スケーラビリティと速度の間の一連のトレードオフです。使用するリソースが少なくなるように調整されたスクリプトは、キャッシュを実行するスクリプトよりも遅くなる可能性がありますが、同じスクリプトのより多くのコピーを Web サーバー上で一度に実行できます。

以下の例では、A.php は速く走ることができる短距離ランナーであり、B.php はほぼ同じ速度で永遠にジョギングできるマラソンランナーです。負荷が軽い場合は、A.php の方が大幅に高速ですが、Web トラフィックが増加すると、B.php のパフォーマンスが少し低下するだけで、A.php は力不足になるだけです。

より現実的な例を見てみましょう。問題をさらに明確にするため。 250K ファイルを読み取り、ファイルの HTML 概要を生成する PHP スクリプトを作成する必要があるとします。同じことを行う 2 つのスクリプトを作成します。hare.php はファイル全体を一度にメモリに読み込み、1 回のパスで処理します。もう 1 つは、一度に 1 行ずつファイルを読み込み、最長行以上は保持しない tortoise.php です。記憶の中で。 Tortoise.php は複数の読み取りが発行されるため遅くなり、より多くのシステムコールが必要になります。

Hare.php は 0.04 秒の CPU と 10 Mb RAM を必要とし、tortoise.php は 0.06 秒の CPU と 5 Mb RAM を必要とします。サーバーには 100 MB の実際の空き RAM があり、CPU は 99% アイドル状態です。話を単純化するために、メモリの断片化が発生しないと仮定します。

10 個のスクリプトを同時に実行すると、hare.php がメモリ不足になります (10 x 10 = 100)。この時点では、tortoise.php にはまだ 50 MB の空きメモリが残っています。 11 番目の同時スクリプトを実行すると、hare.php が仮想メモリの使用を開始し、速度が元の半分程度に低下します。 hare.php の各呼び出しには 0.08 秒の CPU 時間がかかるようになりました。その間、tortoise.php は通常の 0.06 秒の CPU 時間で引き続き実行されます。

以下の表では、さまざまな負荷に対する高速な php スクリプトを太字で示しています:

接続

1 つの HTTP リクエストを満たすのに必要な CPU 秒数

10を満たすのに必要なCPU秒数HTTP リクエスト

11 個の HTTP リクエストを満たすのに必要な CPU 秒数

hare.php

0.04

0.40

0.88
( RAM が不足しています)

tortoise.php

0.06

0.60

0.66

上記の例が示すように、優れたパフォーマンスを得るには、単に高速な PHP スクリプトを作成する必要があります。高性能 PHP を使用するには、基盤となるハードウェア、オペレーティング システム、および Web サーバーやデータベースなどのサポート ソフトウェアをよく理解する必要があります。

ボトルネック

ウサギとカメの例は、ボトルネックが速度低下の原因であることを示しています。無限の RAM を使用すると、hare.php は常に tortoise.php より高速になります。残念ながら、上記のモデルは少し単純化されており、RAM 以外にもパフォーマンスに対するボトルネックが多数あります。

(a) ネットワーク

ネットワークがおそらく最大のボトルネックです。インターネットへの 10 M ビットのリンクがあり、1 秒あたり 1 メガバイトのデータを送信できるとします。各 Web ページが 30k の場合、1 秒あたりわずか 33 Web ページで回線が飽和状態になります。

さらに微妙なネットワークのボトルネックには、DNS などの遅いネットワーク サービスへの頻繁なアクセスや、ネットワーク ソフトウェアへの不十分なメモリの割り当てが含まれます。

(b) CPU

CPU 負荷を監視している場合、ネットワーク経由でプレーン HTML ページを送信しても負担はかかりません前述したように、ボトルネックはネットワークであるため、CPU はまったく必要ありません。ただし、PHP が生成する複雑な動的 Web ページの場合は、通常、CPU 速度が制限要因になります。複数のプロセッサを備えたサーバーを使用するか、サーバー ファームを使用すると、この問題を軽減できます。

(c) 共有メモリ

共有メモリはプロセス間通信に使用され、キャッシュされたデータやコードなどの複数のプロセス間で共有されるリソースを保存します。 。共有メモリが十分に割り当てられていない場合、データベース接続や実行可能コードなどの共有メモリを使用するリソースにアクセスしようとすると、パフォーマンスが低下します。

(d) ファイル システム

ハードディスクへのアクセスは、ハードディスクからのデータの読み取りよりも 50 ~ 100 倍遅くなる可能性があります。ラム。 RAM を使用したファイル キャッシュを使用すると、これを軽減できます。ただし、メモリが少ない状態では、ファイル システム キャッシュに使用できるメモリの量が減少し、動作が遅くなります。ファイル システムが大幅に断片化し、ディスク アクセスが遅くなる場合もあります。 Unix システムでシンボリック リンクを頻繁に使用すると、ディスク アクセスも遅くなる可能性があります。

デフォルトの Linux インストールは、速度ではなく互換性を重視して調整されたハードディスクのデフォルト設定を設定していることでも知られています。 Linux ハードディスク設定を調整するには、hdparm コマンドを使用します。

(e) プロセス管理

Windows などの一部のオペレーティング システムでは、新しいプロセスの作成に時間がかかります。つまり、呼び出されるたびに新しいプロセスをフォークする CGI アプリケーションは、これらのオペレーティング システムでは実行速度が大幅に遅くなります。 PHP をマルチスレッド モードで実行すると、応答時間が改善されます (注: 古いバージョンの PHP はマルチスレッド モードでは安定しません)。

不要なプロセスが多すぎて Web サーバーが過密になることを避けてください。たとえば、サーバーが純粋に Web サービスを目的としている場合は、マシン上で X-Windows を実行 (またはインストール) することは避けてください。 Windows では、CPU 使用率が 100% になる Microsoft Find Fast (Office の一部) および 3D スクリーン セーバーの実行を避けてください。

削除を検討できるプログラムには、未使用のネットワーク プロトコル、メール サーバー、ウイルス対策スキャナ、ハードウェアなどがあります。マウス、赤外線ポートなどのドライバー。 Unix では、SSH を使用してサーバーにアクセスしていると思います。次に、以下を削除することを検討できます:

telnetd、inetd、atd、ftpd、lpd、sambad などのデーモン

受信メールの sendmail
NFS のポートマップ
xfs、fvwm、xinit、X

起動時にさまざまなプログラムを無効にすることもできます通常、/etc/init* または /etc/rc*/init* ディレクトリに保存されている起動ファイルを変更します。

cron ジョブを確認して、それらを削除できるか、オフピーク期間にスケジュールを変更できるかどうかを確認してください。

(f) 他のサーバーへの接続

Web サーバーが他のサーバーで実行されているサービスを必要とする場合、それらのジョブが他のサーバーで実行されている可能性があります。サーバーがボトルネックになります。この最も一般的な例は、複数の Web サーバーからのあまりにも多くの複雑な SQL リクエストを処理している遅いデータベース サーバーです。完了です。このアドバイスが意味をなすのは、プログラミング チームのコーディングがそもそも高品質であり、アプリケーションのパフォーマンス パラメータをすでに十分に把握している場合のみです。そうしないと、テスト後にコードのかなりの部分を書き直さなければならないというリスクにさらされることになります。

私のアドバイスは、ソフトウェア アプリケーションを設計する前に、ハードウェアとソフトウェアの基本的なベンチマークをいくつか実行して、動作の感触を掴む必要があるということです。達成できる可能性のある最大限のパフォーマンス。その後、アプリケーションを設計してコーディングする際には、必要なパフォーマンス パラメーターを念頭に置いてください。これは、あらゆる段階で、パフォーマンス、可用性、セキュリティ、柔軟性の間にトレードオフが存在するためです。

また、適切なテストデータを選択してください。データベースが 100,000 レコードを保持すると予想される場合は、100 レコードのデータベースだけを使用したテストを避けてください。後悔するでしょう。かつて、私の会社のプログラマーの一人にこのようなことが起こりました。遅いコードはかなり後になってから検出され、機能しても拡張できなかった多くのコードを書き直す必要があったため、多くの時間が無駄になりました。現在使用されている 2 つの最も一般的な Web サーバー、Apache 1.3 と IIS で最高の PHP パフォーマンスを得る方法を説明します。ここでのアドバイスの多くは、HTML の提供にも当てはまります。

PHP の作成者は、PHP で Apache 1.3 よりも Apache 2.0 を使用する場合、特にマルチスレッド モードでパフォーマンスやスケーラビリティの利点がないと述べています。 Apache 2.0 をプリフォーク モードで実行する場合、次の議論は依然として重要です (2003 年 10 月 21 日)。
(a) Apache 1.3/2.0

Apache は Unix と Windows の両方で使用できます。世界で最も人気のある Web サーバーです。 Apache 1.3 は、Web サービスに事前フォーク モデルを使用します。 Apache が起動すると、HTTP リクエストを処理する複数の子プロセスが作成されます。最初の親プロセスは守護天使のように機能し、すべての子プロセスが適切に動作していることを確認し、すべてを調整します。より多くの HTTP リクエストが受信されると、それらを処理するためにより多くの子プロセスが生成されます。 HTTP リクエストが遅くなると、親プロセスはアイドル状態の子プロセスを強制終了し、他のプロセスのリソースを解放します。このスキームの利点は、Apache を非常に堅牢にすることです。子プロセスがクラッシュした場合でも、親プロセスと他の子プロセスはクラッシュした子プロセスから隔離されます。

プリフォークモデルは他の考えられる設計ほど高速ではありませんが、私にとっては「大した問題ではない」と思います。 Apache のパフォーマンスの問題が重大になるずっと前に、他のボトルネックが発生するため、PHP スクリプトを提供するサーバーでは実行できません。 Apache の堅牢性と信頼性はより重要です。

Apache 2.0 はマルチスレッド モードでの操作を提供します。私のベンチマークによると、このモードではパフォーマンス上の利点がほとんどありません。また、多くの PHP 拡張機能には互換性がないことにも注意してください (GD や IMAP など)。 Apache 2.0.47 (2003 年 10 月 21 日) でテスト済み。

Apache は httpd.conf ファイルを使用して設定されています。次のパラメータは、子プロセスの設定において特に重要です:

ディレクティブ

Default MaxClients 256 StartServers 5 MinSpareServers 5 MaxSpareServers 10 MaxRequestsPerChild

Description

作成する子プロセスの最大数。デフォルトは、最大 256 の HTTP リクエストを同時に処理できることを意味します。それ以降の接続要求はキューに入れられます。

起動時に作成する子プロセスの数。

作成する必要があるアイドル状態の子プロセスの数。アイドル状態の子プロセスの数がこの数を下回ると、最初に 1 つの子が作成され、次の 2 秒後に 2 つ、さらに 1 秒後に 4 つというように、1 秒あたり 32 の子が作成されるまで続きます。

この数を超える子プロセスが生きている場合、これらの追加のプロセスは終了される。

0

終了する前に子が処理できる HTTP リクエストの数を設定します。 0 に設定すると、決して終了しないことを意味します。メモリ リークが発生していると思われる場合、または十分に活用されていないリソースを解放するには、これを 100 ~ 10000 の値に設定します。

大規模なサイトの場合は、次の値に近い値が適している可能性があります:

MinSpareServers 32

MaxSpareServers 64

Windows 上の Apache は動作が異なります。 Apache は子プロセスを使用する代わりにスレッドを使用します。上記のパラメータは使用されません。代わりに、デフォルトで 50 に設定される ThreadsPerChild という 1 つのパラメータがあります。このパラメータは、Apache によって生成されるスレッドの数を設定します。 Windows バージョンには子プロセスが 1 つしかないため、デフォルト設定の 50 は、50 個の同時 HTTP リクエストのみを処理できることを意味します。 Web サーバーのトラフィックが増加している場合は、この値を 256 から 1024 まで増やしてください。

変更できるその他の便利なパフォーマンス パラメーターには次のものがあります。

説明 TCP/IP接続で使用される出力バッファのサイズ(バイト単位)を決定します。これは主に、パケットをバッファリングする必要がある混雑したネットワークや遅いネットワークで役立ちます。次に、このパラメータを、通常ダウンロードされる最大のファイルのサイズに近い値に設定します。クライアント接続ごとに 1 つの TCP/IP バッファが作成されます。 別の専用 Web サーバーがすべての画像を提供する場合は、このオプションを無効にすることができます。この技術により、リソースの使用率が大幅に向上します。 そうしないとソケットが長時間アイドル状態になるため、この値は低く保つ必要があります。 LimitRequestBody 0 PUT または POST の最大サイズ。 ○は制限がないことを意味します。

SendBufferSize

OSのデフォルトに設定する

KeepAlive [on|off]

On

元の HTTP 仕様では、すべての HTTP リクエストはサーバーへの個別の接続を確立する必要がありました。頻繁な接続のオーバーヘッドを軽減するために、キープアライブ ヘッダーが開発されました。キープアライブは、複数の HTTP リクエストに対して同じソケット接続を再利用するようにサーバーに指示します。

KeepAliveTimeout

15

ソケット接続を維持する秒数。この時間には、サーバーによるコンテンツの生成とクライアントによる確認が含まれます。クライアントが時間内に応答しない場合は、新しい接続を作成する必要があります。

MaxKeepAliveRequests

100

MaxKeepAliveRequests で設定されたリクエスト数に達するとソケット接続が終了しますに達します。これを MaxClients または ThreadsPerChild.

TimeOut

300

アイドル時間がこの値を超えると切断します。クライアントの待機時間が短い場合は、この値をより低く設定できます。

DNS ルックアップが必要なく、htaccess ファイルを使用して個々のディレクトリの Apache 設定を構成していない場合は、以下を設定できます:

# DNS ルックアップを無効にする: PHP スクリプトは IP アドレスのみを取得します

HostnameLookups off

# disable htaccessチェック

b49aa56367fdeb85a9496dde3971aec7

AllowOverride none

bb15ed4aadeed04b3991578461de0768

シンボリック リンクにアクセスするときにディレクトリのセキュリティを心配しない場合は、追加の lstat() システム コールが行われないように、FollowSymLinks をオンにし、SymLinksIfOwnerMatch をオフにします。

Options FollowSymLinks

#Options SymLinksIfOwnerMatch

(b) IISチューニング

IIS は、Windows NT および 2000 で使用できるマルチスレッド Web サーバーです。インターネット サービス マネージャーから、次のパラメータを調整できます:

1 日あたりのヒット数に基づくパフォーマンス チューニング。

IIS に事前に割り当てるメモリの量を決定します。 ([パフォーマンス] タブ)。

帯域幅調整

Web サイトごとに割り当てられる 1 秒あたりの帯域幅を制御します。 ([パフォーマンス] タブ)。

プロセス スロットル

Web サイトごとに使用可能な CPU% を制御します。 ([パフォーマンス] タブ)。

タイムアウト

デフォルトは 900 秒です。ローカル エリア ネットワークでは、より低い値に設定します。 (Web サイト タブ)

HTTP 圧縮

IIS 5 では、動的ページ、HTML、および画像を圧縮できます。圧縮された静的 HTML と画像をキャッシュするように構成できます。デフォルトでは、圧縮はオフになっています。

物理サーバー全体で HTTP 圧縮を有効にする必要があります。これをオンにするには、IIS コンソールを開き、サーバー (サブサイトではなく、左側のペインにあるサーバー) を右クリックし、プロパティを取得します。 [サービス] タブをクリックし、動的コンテンツを圧縮するには [アプリケーション ファイルの圧縮] を選択し、静的コンテンツを圧縮するには [静的ファイルの圧縮] を選択します。

Web サイトのデフォルトの分離レベルを構成することもできます。 [アプリケーション保護] の [ホーム ディレクトリ] タブで、分離レベルを定義できます。高度に分離された Web サイトは、IIS とは別のプロセスとして実行されるため、実行が遅くなります。一方、IIS プロセスで Web サイトを実行するのは最も高速ですが、Web サイトのコードに重大なバグがある場合はサーバーがダウンします。現時点では、CGI を使用して PHP Web サイトを実行するか、アプリケーション保護を高に設定して ISAPI を使用することをお勧めします。

また、regedit.exe を使用して、次の場所に保存されている IIS 5 レジストリ設定を変更することもできます:

HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesInetinfoParameters

MemCacheSize

IIS がファイル キャッシュに使用するメモリの量を設定します。デフォルトでは、IIS は使用可能なメモリの 50% を使用します。 IIS がサーバー上の唯一のアプリケーションの場合は増加します。値はメガバイト単位です。

MaxCachedFileSize

ファイル キャッシュにキャッシュされるファイルの最大サイズをバイト単位で決定します。デフォルトは 262,144 (256K) です。

ObjectCacheTTL

キャッシュ内のオブジェクトがメモリに保持される時間の長さを (ミリ秒単位で) 設定します。デフォルトは 30,000 ミリ秒 (30 秒) です。

MaxPoolThreads

プロセッサごとに作成するプール スレッドの数を設定します。同時に実行できる CGI アプリケーションの数を決定します。デフォルトは 4 です。CGI モードで PHP を使用している場合は、この値を増やします。

ListenBackLog

IIS が接続キュー内で維持するアクティブなキープアライブ接続の最大数を指定します。デフォルトは 15 ですが、サポートしたい同時接続の数まで増やす必要があります。最大値は 250 です。

このレジストリの場所に設定がない場合は、デフォルトが使用されます。

Windows での高いパフォーマンス: IIS と FastCGI

多くのテストを行った結果、IIS と FastCGI を使用することで Windows 上で最高の PHP パフォーマンスが得られることがわかりました。 CGI は、Web サーバーから外部プログラムを呼び出すためのプロトコルです。 CGI プログラムはページ要求のたびに終了するため、それほど高速ではありません。 FastCGI は、ページ リクエスト後に CGI プログラムを永続化し、新しいページ リクエストが来たときに同じ CGI プログラムを再利用することで、このプロトコルを変更して高パフォーマンスを実現します。

IIS での FastCGI のインストールは複雑であるため、EasyWindows を使用する必要があります。 PHPインストーラー。これにより、可能な限り最高のパフォーマンスを得るために、PHP、FastCGI、および Turck MMCache がインストールされます。このインストーラーは、Apache 1.3/2.0 用の PHP もインストールできます。

FastCGI に関するこのセクションは、2003 年 10 月 21 日に追加されました。

PHP4 の Zend エンジン

Zend エンジンは、PHP4 で使用される内部コンパイラおよびランタイム エンジンです。 Zeev Suraski と Andi Gutmans によって開発された Zend Engine は、彼らの名前の略称です。 PHP4 の初期の頃は、次のように動作していました:

PHP スクリプトは Zend Engine によってロードされ、Zend オペコードにコンパイルされました。オペコードは、オペレーション コードの略で、低レベルのバイナリ命令です。次に、オペコードが実行され、生成された HTML がクライアントに送信されました。オペコードは実行後にメモリからフラッシュされました。

現在、このプロセスを高速化するのに役立つ製品や技術が多数あります。次の図は、最新の PHP スクリプトがどのように動作するかを示しています。影付きのボックスはすべてオプションです。

PHP スクリプトはメモリにロードされ、Zend オペコードにコンパイルされます。これらのオペコードは、Zend Optimizer と呼ばれるオプションのピープホール オプティマイザーを使用して最適化できるようになりました。スクリプトに応じて、PHP コードの速度を 0 ~ 50% 向上させることができます。

以前は、実行後にオペコードは破棄されていました。現在は、オプションで、いくつかの代替オープンソース製品と商用クローズドソース製品である Zend Accelerator (旧名 Zend Cache) を使用して、オペコードをメモリにキャッシュできるようになりました。 Zend Optimizer と互換性のある唯一のオペコード キャッシュは、Zend Accelerator です。オペコード キャッシュは、スクリプトの読み込みとコンパイルの手順を削除することで実行を高速化します。オペコード キャッシュを使用すると、実行時間が 10 ~ 200% 改善されます。

オペコード キャッシュの場所

Zend Accelerator: Zend Engine チームによって開発された商用オペコード キャッシュ。非常に信頼性が高く、堅牢です。詳細については、http://zend.com を参照してください。

パフォーマンスと信頼性は、実行する PHP スクリプトに大きく依存するため、本番サーバーで使用する前に、次のオープンソース オペコード キャッシュをテストする必要があります。

Turcke MMCache : http://turck-mmcache.sourceforge.net/ は保守されなくなりました。 eAccelerator を参照してください。これは、アクティブに保守されている mmcache のブランチです (2005 年 2 月 28 日追加)。

代替 PHP キャッシュ: http://apc.communityconnect.com/

PHP アクセラレータ: http://www.php-accelerator .co.uk/

AfterBurner キャッシュ: http://www.bwcache.bware.it/

高いパフォーマンスの秘訣の 1 つは、より高速な PHP コードを記述することではなく、生成された HTML をファイルまたは共有メモリにキャッシュすることで PHP コードの実行を回避することです。 PHP スクリプトは 1 回だけ実行されて HTML がキャプチャされ、その後のスクリプトの呼び出しではキャッシュされた HTML がロードされます。データを定期的に更新する必要がある場合、キャッシュされた HTML に有効期限値が設定されます。 HTML キャッシュは PHP 言語や Zend Engine の一部ではありませんが、PHP コードを使用して実装されます。これを行うクラス ライブラリは数多くあります。そのうちの 1 つは PEAR キャッシュです。これについては次のセクションで説明します。もう 1 つは、Smarty テンプレート ライブラリです。

最後に、Web クライアントに送信される HTML を圧縮できます。これを有効にするには、PHP スクリプトの先頭に次のコードを配置します。

cbb0658a4f80a820abfa75ef78976320

HTML の圧縮率が高い場合は、HTML ファイルのサイズを 50 ~ 80% 削減して、ネットワーク帯域幅の要件と遅延を軽減することができます。欠点は、圧縮のためにある程度の CPU パワーを確保する必要があることです。

PEAR キャッシュを使用した HTML キャッシュ

PEAR キャッシュは、HTML や画像などの複数のタイプのデータをキャッシュできるようにする一連のキャッシュ クラスです。

PEAR キャッシュの最も一般的な用途は、HTML テキストをキャッシュすることです。これを行うには、start() 関数と end() 関数の間で出力またはエコーされたすべてのテキストをキャッシュする出力バッファリング クラスを使用します。 file", array("cache_dir" => "cache/") );

if ($contents = $cache->start(md5("これは一意のキーです!"))) {

#

# ああ、キャッシュされたデータが返されました

#

print $contents;
print "e388a4556c0f65e1904146cc1a846beeキャッシュ ヒット94b3e26ee717c64999d7867364b1b4a3";

} else {


#

# キャッシュ データがないか、キャッシュの有効期限が切れています

#

print "e388a4556c0f65e1904146cc1a846beeこれを持たずに家を出ないでください…94b3e26ee717c64999d7867364b1b4a3"; # キャッシュに配置します
print "e388a4556c0f65e1904146cc1a846bee立って配達94b3e26ee717c64999d7867364b1b4a3"; # キャッシュに配置します
print $cache->end(10);

}

これらの行を書いて以来、優れた PEAR キャッシュ システムが開発されました。より高度な分散キャッシュについては、memcached (2005 年 2 月 28 日追加) を参照してください。

Cache コンストラクターは、最初のパラメーターとして使用するストレージ ドライバーを受け取ります。ファイル、データベース、および共有メモリのストレージ ドライバーが利用可能です。 pear/Cache/Container ディレクトリを参照してください。 Ulf Wendel によるベンチマークは、「ファイル」ストレージ ドライバーが最高のパフォーマンスを提供することを示唆しています。 2 番目のパラメータはストレージ ドライバのオプションです。オプションは、キャッシュ ディレクトリの場所である「cache_dir」と、キャッシュされたすべてのファイルに使用するプレフィックスである「filename_prefix」です。奇妙なことに、キャッシュの有効期限はオプション パラメーターに設定されていません。

一部のデータをキャッシュするには、キーを使用してキャッシュされたデータの一意の ID を生成します。上の例では、md5("this is a unique key!") を使用しました。

start() 関数は、キーを使用してコンテンツのキャッシュされたコピーを検索します。コンテンツがキャッシュされていない場合、start() によって空の文字列が返され、end() が呼び出されるまで、以降のすべての echo() および print() ステートメントが出力キャッシュにバッファリングされます。

end() 関数はバッファの内容を返し、出力バッファリングを終了します。 end() 関数は、最初のパラメータとしてキャッシュの有効期限を受け取ります。このパラメータには、データをキャッシュする秒数、データの有効期限を指定する Unix 整数タイムスタンプ、またはデフォルトの 24 時間のゼロを指定できます。

PEAR キャッシュを使用する別の方法は、変数またはその他のデータを保存することです。 。これを行うには、基本 Cache クラスを使用できます。 ; "cache/") );

$id = $cache->generateID("これは一意のキーです");

if ($data = $cache->get($id)) {

print "キャッシュ ヒットしました。79075c0cfba0f4a0e86ed8bf014e3da2save($id, $data , $expires = 60); print "キャッシュミス。0c6dc11e160d3b678d68754cc175188a";


}

?>

データを保存するには、save() を使用します。一意のキーがすでに有効なファイル名である場合は、generateID() ステップをバイパスできます。 save() がデータをシリアル化するため、オブジェクトと配列を保存できます。最後のパラメータは、データの有効期限がいつ切れるかを制御します。これは、データをキャッシュする秒数、データの有効期限が切れる日時を指定する Unix 整数タイムスタンプ、またはデフォルトの 24 時間を使用する場合はゼロにすることができます。キャッシュされたデータを取得するには、get() を使用します。

$cache->delete($id) を使用してキャッシュされたデータ項目を削除でき、$cache->flush() を使用してキャッシュされたすべての項目を削除できます。

新機能: より高速なキャッシュ クラスは Cache-Lite です。強くお勧めします。

ベンチマークの使用

前のセクションでは、パフォーマンスに関する多くの問題について説明しました。ここで、本質的な部分に移ります。つまり、何を調整すべきかについて適切な情報を取得できるように、コードの測定とベンチマークを行う方法です。

Web サーバー上で現実的なベンチマークを実行したい場合は、HTTP リクエストをサーバーに送信するツールが必要になります。 Unix では、ベンチマークを実行する一般的なツールには、Apache リリースの一部である ab (apachebench の略) と、新しいフラッド (httpd.apache.org/test/flood) が含まれます。 Windows NT/2000 では、Microsoft の無料の Web Application Stress Tool (webtool.rte.microsoft.com) を使用できます。

これらのプログラムは、複数の HTTP リクエストを同時に作成し、複数の Web クライアントをシミュレートし、リクエストの完了に関する詳細な統計を表示できます。テスト

「vmstat 1」を使用して Unix 上でベンチマークが実行されるときにサーバーがどのように動作するかを監視できます。これにより、ディスク I/O、仮想メモリ、CPU 負荷のパフォーマンスに関するステータス レポートが毎秒出力されます。あるいは、「top d 1」を使用すると、実行中のすべてのプロセスが CPU 負荷別にソートされて 1 秒ごとに全画面更新されます。

Windows 2000 では、パフォーマンス モニターまたはタスク マネージャーを使用してシステム統計を表示できます。

HTTP オーバーヘッドを気にせずにコードの特定の側面をテストしたい場合は、マイクロタイムを使用してベンチマークを実行できます。 () は、マイクロ秒単位の正確な現在時刻を文字列として返します。次の関数は、計算に適した数値に変換します。

function getmicrotime()
{
list($usec, $sec) =explode(" ",microtime());
return ((float)$usec + (float)$sec);
}

$time = getmicrotime();

#
# ベンチマークコードはこちら
#

echo "e388a4556c0f65e1904146cc1a846bee経過時間: ", getmicrotime() - $time, " 秒";

あるいは、APD や XDebug などのプロファイリング ツールを使用することもできます。 xdebug を使用してコードを圧縮する私の記事も参照してください。

ベンチマークのケーススタディ

このケーススタディでは、クライアントのために行った実際のベンチマークについて詳しく説明します。この例では、顧客は、長い SQL クエリの実行を含まないすべての PHP ページに対して 5 秒の応答時間を保証したいと考えていました。次のサーバー構成が使用されました: Red Hat 7.2 Linux 上で PHP 4.0.6 を実行する Apache 1.3.20 サーバー。ハードウェアは、1 Gb の RAM を備えたツイン Pentium III 933 MHz の野獣でした。 HTTP リクエストは、PHP スクリプト「testmysql.php」に対するものになります。このスクリプトは、別のサーバーで実行されている MySQL データベースから約 20 レコードを読み取り、処理します。簡単にするために、すべてのグラフィックスが別の Web サーバーからダウンロードされると仮定します。

ベンチマーク ツールとして「ab」を使用しました。 10 の同時接続 (-c10) を使用して、1000 のリクエスト (-n1000) を実行するように「ab」を設定します。結果は次のとおりです。

# ab   -n1000 -c10 http://192.168.0.99/php/testmysql.phpThis is ApacheBench, Version 1.3Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/Copyright (c) 1998-1999 The Apache Group, http://www.apache.org/Server Software:        Apache/1.3.20Server Hostname:        192.168.0.99Server Port:            80Document Path:          /php/testmysql.phpDocument Length:        25970 bytesConcurrency Level:      10Time taken for tests:   128.672 secondsComplete requests:      1000Failed requests:        0Total transferred:      26382000 bytesHTML transferred:       25970000 bytesRequests per second:    7.77Transfer rate:          205.03 kb/s receivedConnnection Times (ms)              min   avg   maxConnect:        0     9   114Processing:   698  1274  2071Total:        698  1283  2185

ベンチマークの実行中、サーバー側でコマンド「top d 1」を使用してリソース使用率を監視しました。パラメータ「d 1」は、更新の間に 1 秒の遅延を意味します。出力を以下に示します。

10:58pm  up  3:36,  2 users,  load average: 9.07, 3.29, 1.7974 processes: 63 sleeping, 11 running, 0 zombie, 0 stoppedCPU0 states: 92.0% user,  7.0% system,  0.0% nice,  0.0% idleCPU1 states: 95.0% user,  4.0% system,  0.0% nice,  0.0% idleMem:  1028484K av,  230324K used,  798160K free,      64K shrd,   27196K buffSwap: 2040244K av,       0K used, 2040244K free                   30360K cached  PID USER     PRI  NI  SIZE  RSS SHARE STAT %CPU %MEM   TIME COMMAND 1142 apache    20   0  7280 7280  3780 R    21.2  0.7   0:20 httpd 1154 apache    17   0  8044 8044  3788 S    19.3  0.7   0:20 httpd 1155 apache    20   0  8052 8052  3796 R    19.3  0.7   0:20 httpd 1141 apache    15   0  6764 6764  3780 S    14.7  0.6   0:20 httpd 1174 apache    14   0  6848 6848  3788 S    12.9  0.6   0:20 httpd 1178 apache    13   0  6864 6864  3804 S    12.9  0.6   0:19 httpd 1157 apache    15   0  7536 7536  3788 R    11.0  0.7   0:19 httpd 1159 apache    15   0  7540 7540  3788 R    11.0  0.7   0:19 httpd 1148 apache    11   0  6672 6672  3784 S    10.1  0.6   0:20 httpd 1158 apache    14   0  7400 7400  3788 R    10.1  0.7   0:19 httpd 1163 apache    20   0  7540 7540  3788 R    10.1  0.7   0:19 httpd 1169 apache    12   0  6856 6856  3796 S    10.1  0.6   0:20 httpd 1176 apache    16   0  8052 8052  3796 R    10.1  0.7   0:19 httpd 1171 apache    15   0  7984 7984  3780 S     9.2  0.7   0:18 httpd 1170 apache    16   0  7204 7204  3796 R     6.4  0.7   0:20 httpd 1168 apache    10   0  6856 6856  3796 S     4.6  0.6   0:20 httpd 1377 natsoft   11   0  1104 1104   856 R     2.7  0.1   0:02 top 1152 apache     9   0  6752 6752  3788 S     1.8  0.6   0:20 httpd 1167 apache     9   0  6848 6848  3788 S     0.9  0.6   0:19 httpd    1 root       8   0   520  520   452 S     0.0  0.0   0:04 init    2 root       9   0     0    0     0 SW    0.0  0.0   0:00 keventd

"top" の出力を見ると、ツイン CPU の Apache サーバーはアイドル時間 0% でフル稼働しています。さらに悪いのは、負荷平均が過去 1 分間で 9.07 (過去 5 分間で 3.29、過去 15 分間で 1.79) であることです。負荷平均は、実行準備ができているプロセスの平均数です。ツイン プロセッサ サーバーの場合、負荷が 2.0 を超えると、システムが過負荷になっていることを意味します。負荷 (9.07) と ab. で定義した同時接続数 (10) の間に密接な関係があることに気づくかもしれません

幸いなことに、約 798,160 MB の空き容量があり、仮想メモリは使用されていないため、十分な物理メモリがあります。 .

さらに下では、CPU 使用率の順にプロセスが表示されます。最もアクティブなものは Apache httpd プロセスです。最初の httpd タスクは 7280K のメモリを使用し、平均して CPU の 21.2%、物理メモリの 0.7% を占有しています。 STAT 列はステータスを示します。R は実行可能、S はスリープ、W はプロセスがスワップアウトされていることを意味します。

上記の数値を考慮し、これが典型的なピーク負荷であると仮定すると、いくつかの計画を実行できます。ツイン CPU サーバーの負荷平均が 9.0 で、各タスクの完了にほぼ同じ時間がかかると仮定すると、負荷の軽いサーバーは 9.0 / 2 CPU = 4.5 倍高速になるはずです。したがって、ピーク負荷時に応答するのに 1.283 秒かかっていた HTTP リクエストは、完了するまでに約 1.283 / 4.5 = 0.285 秒かかります。

To verify this, we benchmarked with 2 simultaneous client connections (instead of 10 in the previous benchmark) to give an average of 0.281 seconds, very close to the 0.285 seconds prediction!

# ab   -n100 -c2 http://192.168.0.99/php/testmysql.php [ some lines omitted for brevity ]Requests per second:    7.10Transfer rate:          187.37 kb/s receivedConnnection Times (ms)              min   avg   maxConnect:        0     2    40Processing:   255   279   292Total:        255   281   332

Conversely, doubling the connections, we can predict that the average connection time should double from 1.283 to 2.566 seconds. In the benchmarks, the actual time was 2.570 seconds.

Overload on 40 connections

When we pushed the benchmark to use 40 connections, the server overloaded with 35% failed requests. On further investigation, it was because the MySQL server persistent connects were failing because of "Too Many Connections".

The benchmark also demonstrates the lingering behavior of Apache child processes. Each PHP script uses 2 persistent connections, so at 40 connections, we should only be using at most 80 persistent connections, well below the default MySQL max_connections of 100. However Apache idle child processes are not assigned immediately to new requests due to latencies, keep-alives and other technical reasons; these lingering child processes held the remaining 20+ persistent connections that were "the straws that broke the Camel's back".

The Fix

By switching to non-persistent database connections, we were able to fix this problem and obtained a result of 5.340 seconds. An alternative solution would have been to increase the MySQL max_connections parameter from the default of 100.

Conclusions

The above case study once again shows us that optimizing your performance is extremely complex. It requires an understanding of multiple software subsystems including network routing, the TCP/IP stack, the amount of physical and virtual memory, the number of CPUs, the behavior of Apache child processes, your PHP scripts, and the database configuration.

In this case the PHP code was quite well tuned, so the first bottleneck was the CPU, which caused a slowdown in response time. As the load increased, the system slowed down in a near linear fashion (which is a good sign) until we encountered the more serious bottleneck of MySQL client connections. This caused multiple errors in our PHP pages until we fixed it by switching to non-persistent connections.

From the above figures, we can calculate for a given desired response time, how many simultaneous HTTP connections we can handle. Assuming two-way network latencies of 0.5 seconds on the Internet (0.25s one way), we can predict:

As our client wanted a maximum response time of 5 seconds, the server can handle up to 34 simultaneous connections per second. This works out to a peak capacity of 34/5 = 6.8 page views per second.

To get the maximum number of page views a day that the server can handle, multiply the peak capacity per second by 50,000 (this technique is suggested by the webmasters at pair.com, a large web hosting company), to give 340,000 page views a day.

Code Optimizations

The patient reader who is still wondering why so much emphasis is given to discussing non-PHP issues is reminded that PHP is a fast language, and many of the likely bottlenecks causing slow speeds lie outside PHP.

Most PHP scripts are simple. They involve reading some session information, loading some data from a content management system or database, formatting the appropriate HTML and echoing the results to the HTTP client. Assuming that a typical PHP script completes in 0.1 seconds and the Internet latency is 0.2 seconds, only 33% of the 0.3 seconds response time that the HTTP client sees is actual PHP computation. So if you improve a script's speed by 20%, the HTTP client will see response times drop to 0.28 seconds, which is an insignificant improvement. Of course the server can probably handle 20% more requests for the same page, so scalability has improved.

The above example does not mean we should throw our hands up and give up. It means that we should not feel proud tweaking the last 1% of speed from our code, but we should spend our time optimizing worthwhile areas of our code to get higher returns.

High Return Code Optimizations

The places where such high returns are achievable are in the while and for loops that litter our code, where each slowdown in the code is magnified by the number of times we iterate over them. The best way of understanding what can be optimized is to use a few examples:

Example 1

Here is one simple example that prints an array:

for ($j=0; $j    echo $arr[$j]."0c6dc11e160d3b678d68754cc175188a";

This can be substantially speeded up by changing the code to:

for ($j=0, $max = sizeof($arr), $s = ''; $j<$max; $j++)
  $s .= $arr[$j]."0c6dc11e160d3b678d68754cc175188a";

echo $s;

まず、式 $j9c681f5d54cfeb159815cb60a4c28d42";

ob_start() による出力バッファリングは、すべての PHP スクリプトのグローバル最適化として使用できることに注意してください。長時間実行されるスクリプトでは、出力バッファを定期的にフラッシュして、何らかのフィードバックが HTTP クライアントに送信されるようにすることもできます。これは ob_end_flush() で実行できます。この関数は出力バッファリングもオフにするため、フラッシュの直後に ob_start() を再度呼び出すことをお勧めします。

要約すると、この例では、ループの不変条件を最適化する方法と、出力バッファリングを使用してコードを高速化する方法を示しました。

例 2

次のコードでは、特別なフォーマット関数を使用して行をフォーマットし、PEAR DB レコードセットを反復処理し、結果をエコーし​​ます。今回は 10.2 ミリ秒で実行時間をベンチマークしました (これにはデータベース接続と SQL 実行時間は含まれません):

function FormatRow(&$recordSet)
{
$arr = $recordSet->fetchRow();
return ' a4b561c25d9afb9ac8dc4d70affff419'.$arr[0].'0d36329ec37a2cc24d42c7229b69747a5a8028ccc7a7e27417bff9f05adf5932'.$arr[1].'72ac96585ae54b6ae11f849d2649d9e6';
}

for ($j = 0; $ j 6e2e54331a81701d054969b57d4f9506numRows(); $j++) {
print FormatRow($rs);
}

例 1 から、コードを次のように変更することでコードを最適化できることがわかりました (実行時間: 8.7 ミリ秒):

function FormatRow(&$recordSet)

{
$arr = $recordSet->fetchRow();
return 'a4b561c25d9afb9ac8dc4d70affff419'.$arr[0].'0d36329ec37a2cc24d42c7229b69747a 5a8028ccc7a7e27417bff9f05adf5932'.$arr[1].'72ac96585ae54b6ae11f849d2649d9e6';
}

ob_start();

for ($j = 0, $max = $rs->numRows(); $ j < $max; $j++) {

print FormatRow($rs);
}

私のベンチマークでは、$max を使用すると 0.5 ミリ秒、ob_start を使用すると 1.5 ミリ秒の高速化に寄与することがわかりました。ループアルゴリズムを変更すると、コードを簡素化して高速化できます。この場合、実行時間は 8.5 ミリ秒に短縮されます:

function FormatRow($arr)

{

return 'a4b561c25d9afb9ac8dc4d70affff419'.$arr[0].'0d36329ec37a2cc24d42c7229b69747a5a8028ccc7a7e27417bff9f05adf5932'.$ arr[1].72ac96585ae54b6ae11f849d2649d9e6';

}

ob_start();

while ($arr = $rs->fetchRow()) {

print FormatRow($arr);

}


One最後の最適化はここで可能です。関数呼び出しのオーバーヘッド (速度のために保守性が犠牲になる可能性があります) を削除して、さらに 0.1 ミリ秒 (実行時間: 8.4 ミリ秒) を短縮できます。 )) {
print 'a4b561c25d9afb9ac8dc4d70affff419'.$arr[0].'0d36329ec37a2cc24d42c7229b69747a5a8028ccc7a7e27417bff9f05adf5932'.$arr[1].'72ac96585ae54b6ae11f849d2649d9e6';

}

切り替えることでPEAR キャッシュに移行すると、キャッシュされたデータの実行時間は再び 3.5 ミリ秒に低下しました:

require_once("Cache/Output.php");


ob_start();

$cache = new Cache_Output("file", array("cache_dir) " => "cache/") );

$t = getmicrotime();

if ($content

刷新评论 刷新页面返顶部

博客园首页 博问 新闻 闪存招聘 知识库

Powered by:

博客园 Copyright © moris



声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
前の記事:PHP オペレーター次の記事:PHP オペレーター