PHPパフォーマンスシリーズ:キャッシングテクニック

中間コードキャッシング(Opcodeキャッシング)

コードキャッシングは、PHPのパフォーマンスを向上させる最も簡単で効率的な方法の1つです。 このタイプのキャッシングを使用すると、コード実行の開始プロセス中に発生する多数の非効率性を取り除くことができます。 コードキャッシングは、ファイルが実行されるたびにPHPコードをコンパイルしないように、中間コードをメモリに保存します。



APCXCacheeAccelerator、 Zend Platformなど、このようなキャッシング用のライブラリが多数あります



ファイル中間キャッシング

大量のコードがあり、サービスが頻繁にアクセスされる場合、各PHPファイルが呼び出されたときに処理されるのを待つことはほとんどありません。この場合、サーバーにコードをアップロードする前にスクリプトを実行して中間コードをすぐに作成することは論理的です。 たとえば、このようなスクリプトのコードは次のように実装できます

/ **

* APC用のファイルのコンパイル

*関数は各ディレクトリを介して実行され、

* apc_compile_fileを介して各* .phpファイルをコンパイルします

* param string $ dir startディレクトリ

* voidを返す

* /

関数compile_files($ dir)

{

$ dirs = glob($ dir。DIRECTORY_SEPARATOR。 '*'、GLOB_ONLYDIR);

if(is_array($ dirs)&& count($ dirs)> 0)

{

while(list(、$ v)= each($ dirs))

{

compile_files($ v);

}

}

$ files = glob($ dir。DIRECTORY_SEPARATOR。 '* .php');

if(is_array($ files)&& count($ files)> 0)

{

while(list(、$ v)= each($ files))

{

apc_compile_file($ v);

}

}

}

compile_files( '/ path / to / dir');




変数キャッシング

ほとんどのキャッシュライブラリでは、変数値をキャッシュできます。 計算(受信)が困難で、変更されない構成値またはデータを保存することは非常に便利です(しばらくの間変更されない場合があり、そのようなキャッシングに基づいて陳腐化したキャッシングを実装できます、翻訳者による注意)。

if(!$ config = apc_fetch( 'config'))

{

require( '/ path / to / includes / config.php');

apc_store( 'config'、$ config);

}


Zend Frameworkの使用とabユーティリティの単純な起動に基づいた実際的な例が示されています;この例では、XML構成の結果がキャッシュに保存されます。 解析時間を短縮すると、構成パラメーターに非常にすばやくアクセスできます。

コード:

if(!$ conf = apc_fetch( 'pbs_config'))

{

$ conf = new Zend_Config_Xml(PB_PATH_CONF。 '/base.xml'、 'production');

apc_store( 'pbs_config'、$ conf);

}


テストチームab -t30 -c5 www.example.com

キャッシングなしの結果

同時実行レベル:5

テストにかかった時間:30.33144秒

完全なリクエスト:684

失敗したリクエスト:0

書き込みエラー:0


キャッシングの結果

同時実行レベル:5

テストにかかった時間:30.12173秒

完全なリクエスト:709

失敗したリクエスト:0

書き込みエラー:0


ご覧のとおり、構成ファイルの値をキャッシュすることにより、パフォーマンスが約3〜4%向上しました。 最適化できる場所は他にもたくさんありますが、そのような場所を見つけると、処理されるリクエストの数が増えます。



ファイル結果のキャッシュ

場合によっては、サーバーは同じコンテンツをもたらすリクエストを処理します。 そのような種類のコンテンツをキャッシュすることは可能です(全体または一部)

このテキストは、 Pear :: Cache_Liteパッケージに基づく例を示しています



完全な出力キャッシュ

多数のソースからのデータを常に更新しているほとんどのサイトでは、完全なキャッシュを行うのは非常に困難です。 これはすべて真実ですが、毎秒データを更新する必要はありません。 サイトの負荷が非常に高い場合でも、5〜10分の遅延で生産性を高めることができます。

次の例では、将来の使用のためにページのスナップショットを保存します。 このアプローチは、多数のユーザーに役立ちます。

このソリューションの使用はお勧めしませんが、高速なものが必要な場合は使用できますが、遅かれ早かれこの方法の欠点がわかります。

ブートストラップキャッシュの例:

require( '/ path / to / pear / Cache / Lite / Output.php');

$ options = array(

'cacheDir' => '/ tmp /'、

'lifeTime' => 10

);

$ cache = new Cache_Lite_Output($オプション);

if(!($ cache-> start($ _ SERVER ['REQUEST_URI'])))

{

require( '/ path / to / bootstrap.php');

$ cache-> end();

}


.htaccessに基づく例:

.htaccess

php_value auto_prepend_file /path/to/cache_start.php

php_value auto_append_file /path/to/cache_end.php

cache_start.php

require( 'Cache / Lite / Output.php');



$ options = array(

'cacheDir' => '/ tmp /'、

'lifeTime' => 10

);

$ cache = new Cache_Lite_Output($オプション);

if(($ cache-> start($ _ SERVER ['REQUEST_URI'])))

出る



cache_end.php

$ cache-> end();


Cache Liteは、ファイルのロック、さまざまなパラメーターのコンテンツの保存方法の決定(この例では、REQUEST URIを使用)など、ほとんどのハードワークを実行します。 $ _POST、$ _COOKIE、および$ _SESSIONの値も必要になる場合があります。



部分キャッシュ

部分キャッシュは、典型的な最適化パスです。 ほとんどの場合、サイトには、ほとんど変更されないか、リアルタイムで変更すべきでない部分があります。 これは、部分キャッシュを適用する必要がある場合に当てはまり、パフォーマンスの向上を確認できます。

文字列値のキャッシュ

require( 'Cache / Lite.php');

$ options = array(

'cacheDir' => '/ tmp /'、

'lifeTime' => 3600 // 1時間

);

$ cache =新しいCache_Lite($オプション);

if(!($カテゴリ= $ cache-> get( 'categories')))

{

$ rs = mysql_query( 'SELECT category_id、category_name FROM category');

$カテゴリ= ' ';

$ cache-> save($カテゴリ、「カテゴリ」);

}

エコー$カテゴリ;


これは単純化された例ですが、価値を保存する柔軟性を示しています。 後でアクセスするために、配列の値を保存できます。

配列値のキャッシュ

require( 'Cache / Lite.php');

$ options = array(

'cacheDir' => '/ tmp /'、

'lifeTime' => 3600、// 1時間

'automaticSerialization' => true

);

$ cache =新しいCache_Lite($オプション);

if(!($カテゴリ= $ cache-> get( 'categories')))

{

$ rs = mysql_query( 'SELECT category_id、category_name FROM category');

$カテゴリ=配列();

while($ row = mysql_fetch_assoc($ rs))

{

$カテゴリ[] = $行;

}

$ cache-> store($カテゴリ、「カテゴリ」);

}

var_dump($カテゴリ);



ご覧のとおり、さまざまなタイプのデータをキャッシュにキャッシュできます。 ただし、データベースクエリの結果を保存するためにファイルキャッシュを使用することはお勧めしません。



RAMキャッシング

メモリでキャッシュを実行するには、memcached、データベースのメモリテーブル、RAMディスクなど、さまざまな方法があります。

Memcached

memcacheサイトのmemcachedは、データベースからの負荷を減らすことで動的なWebアプリケーションの速度を向上させる高性能で分散型のキャッシュシステムです。

つまり、memcachedはほとんどの場合デーモンであるため、他のサーバーからアクセスされる1つのサーバーにデータを保存でき、Webサーバーに依存しません(中間コードをキャッシュする場合のように)。ケースは、データベースのクエリ結果をキャッシュするために使用されます。

Memcacheの例:

$ post_id =(int)$ _GET ['post_id'];

$ memcached =新しいmemcache;

$ memcached-> connect( 'hostname'、11211);

if(!$ row = $ memcached-> get( 'post_id_'。$ post_id))

{

//はい、これは安全です。既にキャスト済みです;)

$ rs = mysql_query( 'SELECT * FROM post WHERE post_id ='。$ post_id);

if($ rs && mysql_num_rows($ rs)> 0)

{

$ row = mysql_fetch_assoc($ rs);

// 1時間圧縮されたキャッシュ

$ memcached-> set( 'post_id _'。$ post_id、$ row、MEMCACHE_COMPRESSED、time()+ 3600);

}

}

var_dump($行);


これは非常に単純なmemcachedの例です。 将来の使用に備えてメモリ内に単純な要素を保持しており、将来的には簡単にアクセスできるようになります。 最も頻繁にアクセスするデータには、この方法を使用することをお勧めします。

Memcacheを操作するためのセッションパラメーターの設定例

session.save_handler = memcache

session.save_path = "tcp://ホスト名:11211"



ご覧のとおり、セッションのサポートは非​​常に簡単です。 memcachedサーバーが多数ある場合、save_path変数には、各サーバーでコンマで区切られたサーバー名を含める必要があります。

メモリテーブルデータベース

データベースのメモリテーブルを使用して、セッションデータを保存できます。 MySQLを使用してこのタイプのテーブルを作成できます。 独自のセッションハンドラを作成します。 これは、セッションパフォーマンスを向上させる1つの方法です。

RAMディスク

RAMをディスクとして使用するアプローチは配布の例ではありませんが、このアプローチはサイトのパフォーマンスを向上させるために簡単に適用できます。 このようなディスクにある情報は、サーバーの再起動後に消えることを忘れないでください。

RAMディスクの作成
mount --bind -ttmpfs / path / to / site / tmp / path / to / site / tmp


私はこのアプローチの回避を試みます。なぜなら、この場合のリスクは、多数のサーバーに関しては利点よりも重要だと考えているからです。 この場合、最適な方法はmemcachedを使用することです。



上記が非常に有益であることを願っています。 ここでは、分散データベースでのキャッシュの使用やSquidの使用など、キャッシュの可能性のすべてについては説明しません。 今後の記事では、これについて説明します...



All Articles