Y-110's Wiki


PHP:eAccelerator で PHP 高速化

このページをdel.icio.usに追加 このページをはてなブックマークに追加このページを含むはてなブックマーク このページをlivedoor クリップに追加このページを含むlivedoor クリップ このページをYahoo!ブックマークに追加このページを含むYahoo!ブックマーク

_ eAccelerator で PHP 高速化

アクセラレータはスクリプトを解析した結果を中間コード(バイトコード)の状態で共有メモリ上にキャッシュします。
スクリプトの2回目以降の実行は構文解析を行わずに, キャッシュされた中間コードをダイレクトに読み込むことで処理を高速化しています。
巨大なソースファイル多数のファイルをインクルードしているケースでは, アクセラレータは絶大な威力を発揮します。

PHP向けに様々なアクセラレータが公開されていますが, 有名なのは以下の3つでしょう。*1

PHP5 を使用しているならば, 選択肢は eAccelerator か APC に限られてしまいます。(PHPA は PHP5 に対応していません。)

この中で個人的にオススメなのが, eAccelerator です。
理由は単純にこの中で一番速いからです。

_ PHPA との速度比較

某案件にて, PHPA と eAccelerator で速度比較を行いました。
同時接続数16, リクエスト数100でトップページを ab(Apache Bench) でベンチマークした結果は以下の様になりました。*2

環境
CPU: Intel(R) Pentium(R) 4 CPU 3.20GHz(L2 1MB)
Mem: 1GB
PHP: 4.3.9
Apache: 1.3.33
eAccelerator: 0.9.3
-eAccelerator
Concurrency Level:      16
Time taken for tests:   4.263 seconds
Complete requests:      100
Failed requests:        0
Broken pipe errors:     0
Total transferred:      564366 bytes
HTML transferred:       544476 bytes
Requests per second:    23.46 [#/sec] (mean)
Time per request:       682.08 [ms] (mean)
Time per request:       42.63 [ms] (mean, across all concurrent requests)
Transfer rate:          132.39 [Kbytes/sec] received
-PHPA
Concurrency Level:      16
Time taken for tests:   6.289 seconds
Complete requests:      100
Failed requests:        0
Broken pipe errors:     0
Total transferred:      561496 bytes
HTML transferred:       538569 bytes
Requests per second:    15.90 [#/sec] (mean)
Time per request:       1006.24 [ms] (mean)
Time per request:       62.89 [ms] (mean, across all concurrent requests)
Transfer rate:          89.28 [Kbytes/sec] received
-アクセラレータ無し
Concurrency Level:      16
Time taken for tests:   12.140 seconds
Complete requests:      100
Failed requests:        0
Broken pipe errors:     0
Total transferred:      553300 bytes
HTML transferred:       533800 bytes
Requests per second:    8.24 [#/sec] (mean)
Time per request:       1942.40 [ms] (mean)
Time per request:       121.40 [ms] (mean, across all concurrent requests)
Transfer rate:          45.58 [Kbytes/sec] received

アクセラレータを使わない場合に比べて, PHPA は約2倍, eAccelerator は約3倍処理速度が向上しました。
APC との速度比較は行ったことはないのですが, こちらによると PHPA ≒ APC という結果になったようです。
今まで私が使用した限りでは eAccelerator に関しては安定して動作しています*3ので, 安定面でも特に問題ないと思います。*4

_ メモリ使用状況

memory_usage.png

こちらは PHPA から eAccelerator(0.9.5) に変更した際のメモリリソースグラフです。*5
火曜日に入れ替え作業を行ったのですが, 見て分かる通り apps で使用されるメモリも安定しており, それに伴い active や committed の値も低くなっています。
もちろんアプリケーションの変更は行っていませんし, アクセラレータ用に確保した共有メモリも同じサイズです。
環境にもよるのでしょうが, eAccelerator は PHPA よりメモリを上手に使ってくれるようです。

_ インストール

SourceForge:eAccelerator から最新パッケージをダウンロードします。
現時点(2006/6/6)での最新版は 0.9.5-beta2 です。

# tar jxvf eaccelerator-0.9.5-beta2.tar.bz2 && cd eaccelerator-0.9.5-beta2
# phpize
# ./configure --enable-eaccelerator=shared --with-php-config=/path/to/php-config
# make && make install

extension_dir 以下に eaccelerator.so がインストールされます。

make 時に libtool 関係のエラーがでた場合は, export SED=sed で環境変数を設定してやるとうまくいくかも知れません。
また --enable-versioning で PHP をコンパイルすると, httpd 起動時に undefined symbol: _zval_ptr_dtor というエラーがでる場合がありますので, eAccelerator を導入する際には --disable-versioning をつけてコンパイルする方が無難です。

_ 設定

php.ini に eAccelerator の設定項目を追加します。

[eaccelerator]
zend_extension="/usr/local/lib/php/extensions/no-debug-non-zts-20050922/eaccelerator.so"
eaccelerator.shm_size = "32"
eaccelerator.cache_dir = "/home/php/cache/eaccelerator"
eaccelerator.enable = "1"
eaccelerator.optimizer = "1"
eaccelerator.check_mtime = "1"
eaccelerator.debug = "0"
eaccelerator.filter = ""
eaccelerator.shm_max = "0"
eaccelerator.shm_ttl = "0"
eaccelerator.shm_prune_period = "0"
eaccelerator.shm_only = "0"
eaccelerator.compress = "1"
eaccelerator.compress_level = "9"
eaccelerator.keys     = "shm_and_disk"
eaccelerator.sessions = "shm_and_disk"
eaccelerator.content  = "shm_and_disk"

各設定項目の意味は以下の通りです。

設定項目デフォルト値説明
shm_size0eAcceleratorが使用する共有メモリサイズ。0 は OS のデフォルト値が使用される。
cache_dir/tmp/eacceleratorディスクキャッシュが保存されるディレクトリ。共有メモリにも同じデータが格納される。
enable1eAccelerator を有効にするかどうか。0 が無効で 1 が有効。以下のオプションも同様。
optimizer1内部オプティマイザを有効にするかどうか。オプティマイザを有効にするとコードの実行が速くなる。
debug0デバッグログを出力するかどうか。
check_mtime1ファイルの変更をチェックするかどうか。変更チェックしないとその分軽くなるが, ファイルの修正を検出できなくなるので注意。
filter""キャッシュするファイルをワイルドカード等(*.php)で指定する。!から始まるパターンはキャッシュしない。デフォルトでは全ての PHPスクリプトをキャッシュする。
shm_max01キャッシュの共有メモリにおける最大サイズ。バイトで指定(10240, 10K, 1M)する。0 は制限無し。
shm_ttl0共有メモリの取得に失敗した場合に, shm_ttl(秒)以上経過したスクリプトを削除する。0 は削除しない。
shm_prune_period0共有メモリの取得に失敗した場合に,前回の取得動作から shm_prune_period(秒)以上経過して場合に, 古いスクリプトを削除する(shm_ttl と関連あり)。0 は削除しない。
shm_only0共有メモリにのみキャッシュするかどうか。0 はディスクキャッシュと併用。
compress1キャッシュ内容の圧縮を行うかどうか。
compress_level9キャッシュ圧縮レベル。9が最大値。
name_space""key の前につけるプレフィックス文字列。同一キー名・同一ホスト上で2つ以上のアプリケーションが動作する場合に設定する。
keysshm_and_diskどこにキャッシュされるかを指定する。shm_and_disk は共有メモリとディスクに保存。shm は基本的に共有メモリだが shm_size や shm_max を超えた場合にはディスクに保存。shm_only は共有メモリにのみ保存。disk_only はディスクにのみ保存。none はデータをキャッシュしない。
sessions
content

オプションは多々ありますが, 基本的に shm_size のみ設定して, 他の項目はソースに添付されている eaccelerator.ini の値を使用して問題ないと思います。
通常のサイトだと shm_size は 16〜32(M) で十分でしょう。

_ 動作確認

  • CLI版
    以下の様に表示されれば OK です。
$ php -v 
PHP 5.1.4 (cli) (built: May 22 2006 18:18:31)
Copyright (c) 1997-2006 The PHP Group
Zend Engine v2.1.0, Copyright (c) 1998-2006 Zend Technologies
    with eAccelerator v0.9.5-beta2, Copyright (c) 2004-2006 eAccelerator, by eAccelerator
  • Apache module版
    phpinfo() を実行して, eAccelerator の項目があるかどうかを確認します。
ea_phpinfo2.jpg

正常にロードされていると, Configuration の手前に CLI版と同じメッセージも表示されています。

ea_phpinfo.jpg

実際に eAccelerator が使われているかどうかは以下の方法で確認して下さい。

  • ディスクキャッシュ有効(shm_disk等)
    • cache_dir に eaccelerator-xxx.xxxx の名前でキャッシュファイルが生成されるかを確認
  • キャッシュヒット
    • eaccelerator.debug=1 で error_log を確認して, EACCELERATOR hit: "xxx" と表示されていたら OK

eAccelerator が正常に動作していることが確認できたら, ab でベンチマークを取ってみましょう。

_ キャッシュコントロール

キャッシュの利用状況は phpinfo() でも確認出来ますが, ソースツリーの中にある control.php を使うとわかりやすく表示してくれます。*6
control.php を Webからアクセスできる場所にコピーしてアクセスするとキャッシュコントロール画面が表示されます。*7
ベーシック認証のデフォルトユーザ名/パスワードは admin/eAccelerator です。

共有メモリを使い切っている場合は, shm_size を調整しましょう。

control.jpg

本来ならここからキャッシュの ON/OFF 等の操作ができるようですが, 試したところうまく動きませんでした。
まだβ版だからなのか設定がまずいのかわからないですが, ハマるのも嫌なのでこの項目は正常に動作してから編集します。

_ 例外処理

PHP5 から導入された例外処理ですが, eAccelerator 0.9.5-1 までは optimizer を有効にすると Fatal error になってしまうという現象が発生します。*8

 <?php
 try {
     throw new Exception('例外が発生しました。');
 } catch (Exception $e) {
     echo $e->getMessage() . "<br />";
     echo '後始末。';
 }
 ?>

このコードを実行しても期待通りに例外がキャッチされずに, 以下の様にエラーになってしまいます。

 Fatal error: Uncaught exception 'Exception' with message '例外が発生しました。' in /path/to/ex.php:3 Stack trace: #0 {main} thrown in /path/to/ex.php on line 3

例外処理が使えない, ということで他のアクセラレータの使用を余儀なくされた方もいると思いますが, eAccelerator 0.9.5-2 ではこのバグが修正されています。

0.9.5-2 にアップグレードして実行した結果は期待通りとなりました。

 例外が発生しました。
 後始末。

_ 注意点

eAccelerator を含むアクセラレータは確かに PHP の実行を高速化します。
これは構文解析処理をパスして, 直接中間コードを実行することによって得られるものです。

PHPのスクリプトの内部で複雑な計算・巨大な配列のループ処理などを行ったり, データベースへ重い SQL を発行したり, といったようなアプリケーションの本来の仕事に時間がかかっている場合は, アクセラレータを入れたとしてもさほど効果は得られません。
この場合は, 地道にスクリプトや SQL を改善していくしかないでしょう。 *9

アクセラレータは万能薬ではありませんのでご注意を。

 


Zend Optimizer は有料なので除外・・・と書いてましたが無料化されたみたいですね


Apache と ab を実行したサーバは同一サーバ上なので, 通信コストはほぼ無視できます


MMCache 時代は割と不安定で, httpd を巻き込んで落ちることも結構ありました・・・。


環境によっては動作がおかしくなる場合もあるかもしれません。ハマりそうだったら素直に PHPA や APC を入れましょう。


Munin いいっすよ (^^)


eAccelerator-0.9.4 までは eaccelerator.php という名前です。


0.9.4 までとは雰囲気がだいぶ変わっていますね。


optimizer を無効にするとこの現象は回避できるのですが, それではアクセラレータの意味がありませんよね (^^;


自動車に例えると, エンジン性能は良くなりますが, 乗り手が下手だと結局は速く走れないようなものです。


 
添付ファイル: filememory_usage.png 1225件 [詳細] filecontrol.jpg 1391件 [詳細] fileea_phpinfo2.jpg 1811件 [詳細] fileea_phpinfo.jpg 1045件 [詳細]
 
Link: 負荷対策概論(1285d) FrontPage(1373d)
Last-modified: 2008-02-06 (水) 18:02:25 (905d)