CentOS6でAPCを使ってOpcodeキャッシュを利用する方法をまとめました。
※目次をクリックすると目次の下部にコンテンツが表示されます。
PHP Opcodeキャッシュの概要
1)PHP Opcodeキャッシュとは
・PHPはスクリプト処理言語で、C言語のようなコンパイル言語と比べて実行前にコンパイルする手間は省けるが実行時にはコンパイル言語と比べて追加の処理が必要で速度が遅くなる。
●PHPの実行ステップ概要
①ウェブクライアントからのリクエストを受け取るとPHPスクリプトの読み込みとパースを行い、PHPのバイトコード(opcode)にコンパイルする
②Zendエンジンがopcodeを実行する。
・ウェブクライアントからのリクエストを受け取るたびに上記処理を行う必要があり、ウェブサーバーのCPUやファイルシステムに負荷をかけてしまう。
opcodeキャッシュを使うと、コンパイル済みのスクリプトのバイトコードを共有メモリに置き、同じスクリプトが再びリクエストされたときには、このバイトコードを再利用する。
2)Opcodeキャッシュの代表的なツール
・XCache
・MMCache
・Alternative PHP Cache(APC)
・PHPはスクリプト処理言語で、C言語のようなコンパイル言語と比べて実行前にコンパイルする手間は省けるが実行時にはコンパイル言語と比べて追加の処理が必要で速度が遅くなる。
●PHPの実行ステップ概要
①ウェブクライアントからのリクエストを受け取るとPHPスクリプトの読み込みとパースを行い、PHPのバイトコード(opcode)にコンパイルする
②Zendエンジンがopcodeを実行する。
・ウェブクライアントからのリクエストを受け取るたびに上記処理を行う必要があり、ウェブサーバーのCPUやファイルシステムに負荷をかけてしまう。
opcodeキャッシュを使うと、コンパイル済みのスクリプトのバイトコードを共有メモリに置き、同じスクリプトが再びリクエストされたときには、このバイトコードを再利用する。
2)Opcodeキャッシュの代表的なツール
・XCache
・MMCache
・Alternative PHP Cache(APC)
CentOS6にAPCをインストール
PHPの実行コード(Opcode)をキャッシュすることができるAlternative PHP Cache (APC)をCentOS6にインストールする方法です。
〇実行環境
・CentOS6
・PHP5.3.3
1)peclの環境を構築
APCはpeclを介してインストールするので、まずpeclの環境を構築します。
①peclを含むパッケージを検索
yumを使ってpeclを含むパッケージを検索します。
〇実行環境
・CentOS6
・PHP5.3.3
1)peclの環境を構築
APCはpeclを介してインストールするので、まずpeclの環境を構築します。
①peclを含むパッケージを検索
yumを使ってpeclを含むパッケージを検索します。
# yum provides "*/pecl" 1:php-pear-1.9.4-4.el6.noarch : PHP Extension and Application Repository : framework Repo : base Matched from: Filename : /usr/bin/pecl php-pecl-http1-1.7.6-4.el6.i686 : Extended HTTP support Repo : epel Matched from: Filename : /usr/share/pear/pecl
②php-pecl-http
php-pearとphp-pecl-httpの二つがありましたが、とりあえずphp-pecl-httpをインストールしてみました。
# yum install php-pecl-http Installed: php-pecl-http.i686 0:2.2.1-1.el6 Dependency Installed: php-pear.noarch 1:1.9.4-4.el6 php-pecl-propro.i686 0:1.0.0-1.el6 php-pecl-raphf.i686 0:1.0.4-1.el6.1 Complete!
php-pearに依存していてこちらもインストールされました。
2)APCをインストール
①APCインストール時に”ERROR: `phpize’ failed”が発生したら?
# pecl install apc WARNING: channel "pecl.php.net" has updated its protocols, use "pecl channel-update pecl.php.net" to update downloading APC-3.1.13.tgz ... Starting to download APC-3.1.13.tgz (171,591 bytes) .................................done: 171,591 bytes 55 source files, building running: phpize sh: phpize: コマンドが見つかりません ERROR: `phpize' failed
●php-develをインストール
・phpizeを含むパッケージを検索
# yum provides "*/phpize" php-devel-5.3.3-40.el6_6.i686 : Files needed for building PHP extensions Repo : updates Matched from: Filename : /usr/bin/phpize
・php-develをインストール
# yum install php-devel Installed: php-devel.i686 0:5.3.3-40.el6_6 Dependency Installed: autoconf.noarch 0:2.63-5.1.el6 automake.noarch 0:1.11.1-4.el6 Complete!
②APCインストール時に”pcre.hがない”が発生したら?
# pecl install apc /usr/include/php/ext/pcre/php_pcre.h:29:18: error: pcre.h: そのようなファイルや ディレクトリはありません
●pcre-develをインストール
・pcre.hを含むパッケージを検索
# yum provides "*/pcre.h" pcre-devel-7.8-6.el6.i686 : Development files for pcre Repo : base Matched from: Filename : /usr/include/pcre.h
・pcre-develをインストール
# yum install pcre-devel Installed: pcre-devel.i686 0:7.8-6.el6 Complete!
③APCをインストール 成功の場合
# pecl install apc WARNING: channel "pecl.php.net" has updated its protocols, use "pecl channel-update pecl.php.net" to update downloading APC-3.1.13.tgz ... Starting to download APC-3.1.13.tgz (171,591 bytes) .....................................done: 171,591 bytes 55 source files, building running: phpize Configuring for: PHP Api Version: 20090626 Zend Module Api No: 20090626 Zend Extension Api No: 220090626 Enable internal debugging in APC [no] : Enable per request file info about files used from the APC cache [no] : Enable spin locks (EXPERIMENTAL) [no] : Enable memory protection (EXPERIMENTAL) [no] : Enable pthread mutexes (default) [no] : Enable pthread read/write locks (EXPERIMENTAL) [yes] : Build process completed successfully Installing '/usr/include/php/ext/apc/apc_serializer.h' Installing '/usr/lib/php/modules/apc.so' install ok: channel://pecl.php.net/APC-3.1.13 configuration option "php_ini" is not set to php.ini location You should add "extension=apc.so" to php.ini
3)PHPの初期設定ファイルの編集
PHPの初期設定ファイルに拡張モジュールの設定を行います。
上記のようにphp.iniに設定することもできますが、私の環境では/etc/php.d/ディレクトリ内で拡張モジュール名.iniの名前のファイル内に設定する方法が取られているのでそのように設定しました。
vi /etc/php.d/apc.ini
extension=apc.so
APCのチューニング方法
1)キャッシュの設定、ステータスの詳細情報を確認
①apc.phpをドキュメントルートに配置
/usr/share/pear/apc.php
②ブラウザからapc.phpにアクセス
キャッシュの設定値、ステータスを確認できます。
2)APCにどれくらいの共有メモリを設定するか?
①デフォルト状態
私の環境では(CentOS6、Apache2.2.15、PHP5.3.3、APC3.1.13)では、apc.phpで確認すると下記のようになっていました。
1 Segment(s) with 32.0 MBytes
(mmap memory, pthread read/write Locks locking)
②mmap(メモリマッピング)かSHM(SysⅤ共有メモリ)か?
コンパイル時に–enable-mmapのように指定して、mmapとSHMを選択できるようです。私の環境では、mmapに設定されているようです。
●mmap
・ひとつのメモリセグメントだけを使用。
・一般的には MMAPサポートを推奨。ウェブサーバーを再起動するよりも高速にメモリを再利用するし、起動時のメモリ割り当て量も軽減できるため。
●SHM
・複数のメモリセグメントを使用。
③共有メモリのサイズ設定
●apc.shm_size
・個々の共有メモリセグメントの大きさを MB 単位で指定。デフォルトは32MB。
●apc.shm_segments(SHMの場合のみ)
・コンパイラキャッシュのために割り当てる共有メモリセグメントの数。mmapの場合はセグメントを一つしか使用しないので意味を持たない。
2)キャッシュがFullの場合の振る舞い、TTL(Time-To-Live)の設定
・キャッシュがFullになった場合、apc.ttlで設定された時間アクセスがなかったエントリが強制削除される。
・apc.ttlが0(デフォルト)の場合は、キャッシュがFullになるとすべてのエントリが強制削除される。
・0より大きい場合は、APC は期限切れのエントリの削除を試みる。
3)スクリプトの変更チェックの方法
①設定パラメータ
●apc.stat integer
・デフォルト設定はOnで、ファイルが変更されていないかどうかをスクリプトの実行のたびにAPCが調べ、もし変更されていれば、再コンパイルして新しいバージョンをキャッシュする。
・この設定をOffにすると、変更されているかどうかがチェックされない。つまり、変更内容を有効にするにはWebサーバーを再起動する必要があるということ。
実運用環境でコードを変更することが少ない場合は、この設定をOffにしておくことでパフォーマンスを大きく向上させられる。
●apc.stat_ctime integer
・APCはファイル変更チェックの際、通常はmtimeのみを確認するが、svnやrsyncでは、ファイルの中身を変更していないのにmtimeを変更するといった場合が起こりうる。
ctimeによる検証を行えば、直近の状態からinodeが変わっていないことを確実に確かめ、このような問題を回避することができる。
4)ロックに関する設定
●apc.write_lock boolean
・多くの処理が実行されるサーバーでは、最初にサーバーを立ち上げたときや 多くのファイルを変更した場合などに、 すべてのプロセスが同一のファイルをコンパイルしたりキャッシュしたりしてしまうことがある。
この設定を有効にすると、ひとつのプロセスのみが未キャッシュのスクリプトをコンパイルするようになる。
その間、他のプロセスはロック待ちをするのではなくキャッシュされていない状態で実行する。
5)APCで特定のファイル、ディレクトリを指定してキャッシュ
①設定パラメータ
●apc.cache_by_default boolean
・デフォルトすべてのファイルをキャッシュ(On)にするかキャッシュしないか(Off)を指定。
●apc.filters string
・カンマで区切られた、POSIX 拡張正規表現のリスト。
・マッチングに使用されるファイル名はinclude/requireに渡される名前であり、絶対パスではないことに注意する。
・正規表現が + で始まっている場合、その条件にマッチするファイルはキャッシュされ、- で始まっている場合は、条件にマッチするファイルはキャッシュされない。
②設定例
●デフォルトはすべてのファイルをキャッシュし、指定したファイルのみキャッシュ対象から外す
apc.cache_by_default = 1
apc.filters = “-/var/www/html/big.php, -/var/www/html/some_dir/.*”
●デフォルトはすべてのファイルをキャッシュせず、指定したファイルのみキャッシュする
apc.cache_by_default = 0
apc.filters = “+/var/www/html/some_dir/.*”
①apc.phpをドキュメントルートに配置
/usr/share/pear/apc.php
②ブラウザからapc.phpにアクセス
キャッシュの設定値、ステータスを確認できます。
2)APCにどれくらいの共有メモリを設定するか?
①デフォルト状態
私の環境では(CentOS6、Apache2.2.15、PHP5.3.3、APC3.1.13)では、apc.phpで確認すると下記のようになっていました。
1 Segment(s) with 32.0 MBytes
(mmap memory, pthread read/write Locks locking)
②mmap(メモリマッピング)かSHM(SysⅤ共有メモリ)か?
コンパイル時に–enable-mmapのように指定して、mmapとSHMを選択できるようです。私の環境では、mmapに設定されているようです。
●mmap
・ひとつのメモリセグメントだけを使用。
・一般的には MMAPサポートを推奨。ウェブサーバーを再起動するよりも高速にメモリを再利用するし、起動時のメモリ割り当て量も軽減できるため。
●SHM
・複数のメモリセグメントを使用。
③共有メモリのサイズ設定
●apc.shm_size
・個々の共有メモリセグメントの大きさを MB 単位で指定。デフォルトは32MB。
●apc.shm_segments(SHMの場合のみ)
・コンパイラキャッシュのために割り当てる共有メモリセグメントの数。mmapの場合はセグメントを一つしか使用しないので意味を持たない。
2)キャッシュがFullの場合の振る舞い、TTL(Time-To-Live)の設定
・キャッシュがFullになった場合、apc.ttlで設定された時間アクセスがなかったエントリが強制削除される。
・apc.ttlが0(デフォルト)の場合は、キャッシュがFullになるとすべてのエントリが強制削除される。
・0より大きい場合は、APC は期限切れのエントリの削除を試みる。
3)スクリプトの変更チェックの方法
①設定パラメータ
●apc.stat integer
・デフォルト設定はOnで、ファイルが変更されていないかどうかをスクリプトの実行のたびにAPCが調べ、もし変更されていれば、再コンパイルして新しいバージョンをキャッシュする。
・この設定をOffにすると、変更されているかどうかがチェックされない。つまり、変更内容を有効にするにはWebサーバーを再起動する必要があるということ。
実運用環境でコードを変更することが少ない場合は、この設定をOffにしておくことでパフォーマンスを大きく向上させられる。
●apc.stat_ctime integer
・APCはファイル変更チェックの際、通常はmtimeのみを確認するが、svnやrsyncでは、ファイルの中身を変更していないのにmtimeを変更するといった場合が起こりうる。
ctimeによる検証を行えば、直近の状態からinodeが変わっていないことを確実に確かめ、このような問題を回避することができる。
4)ロックに関する設定
●apc.write_lock boolean
・多くの処理が実行されるサーバーでは、最初にサーバーを立ち上げたときや 多くのファイルを変更した場合などに、 すべてのプロセスが同一のファイルをコンパイルしたりキャッシュしたりしてしまうことがある。
この設定を有効にすると、ひとつのプロセスのみが未キャッシュのスクリプトをコンパイルするようになる。
その間、他のプロセスはロック待ちをするのではなくキャッシュされていない状態で実行する。
5)APCで特定のファイル、ディレクトリを指定してキャッシュ
①設定パラメータ
●apc.cache_by_default boolean
・デフォルトすべてのファイルをキャッシュ(On)にするかキャッシュしないか(Off)を指定。
●apc.filters string
・カンマで区切られた、POSIX 拡張正規表現のリスト。
・マッチングに使用されるファイル名はinclude/requireに渡される名前であり、絶対パスではないことに注意する。
・正規表現が + で始まっている場合、その条件にマッチするファイルはキャッシュされ、- で始まっている場合は、条件にマッチするファイルはキャッシュされない。
②設定例
●デフォルトはすべてのファイルをキャッシュし、指定したファイルのみキャッシュ対象から外す
apc.cache_by_default = 1
apc.filters = “-/var/www/html/big.php, -/var/www/html/some_dir/.*”
●デフォルトはすべてのファイルをキャッシュせず、指定したファイルのみキャッシュする
apc.cache_by_default = 0
apc.filters = “+/var/www/html/some_dir/.*”