APCの動作 3 設計と設定
APCの設定というと、FacebookでのAPC使用方法を紹介したapc@facebookがとっても有用。
内容については、id:i_ogiさんがまとめられているfacebookでのAPCの設定というエントリーを読むのがおすすめ。
といっても、APCを使うサイト全てがFacebook並みの規模があるわけでもないので、apc@facebookを横目で見ながら目の前のサイトに合った設定を探すのだ。(Userキャッシュは使ってないので無視だ)
apc.shm_size
使用するメモリのサイズ。キャッシュ対象の全ファイルがキャッシュされた状態でも余りが出るように設定する。
ただし、1KBのファイルが1KBのメモリを消費するわけではないので注意。
目安としては
クラス > 関数 > ベタ書き処理 > テキスト
の順で元よりサイズが大きくなる。元のファイルサイズの大体5〜6倍程度で計算すれば良いと思う。
実際のサイズはapc.phpやapc_cache_info()で確認できる。
割り当てられるメモリが少ないとか、PHPの量がとんでもないという場合にはapc.filtersを使って除外してみる。呼び出しが多い共通のクラスはキャッシュして、場末のSmartyコンパイルキャッシュは外すなど。
そのためには正規表現が書きやすいようなディレクトリ構成やファイル命名規則にしておく必要がある。
メモリの割り当てが少ないとexpunge(Cache full)が発生してしまう。
expungeはパフォーマンスに悪影響を与えるので可能な限り避ける。
apc.stat
これが一番悩ましい。
offにした方が通常時のパフォーマンスは良いのだろうけど、管理上の問題がある。
offの場合はファイルの更新をした後にサーバの再起動かapc_cache_clear()を実行する必要があるけど、そうすると全てのキャッシュが消えてしまう。
キャッシュが消えた後で一気にアクセスが来ると、各プロセスがキャッシュを作ろうとしてあんまり良くない*1。
それに、滅多に呼ばれないファイルを更新しただけの場合でも、必ず呼ばれるファイルのキャッシュを消さなきゃならないのも嬉しくない。
サーバを切り離してapc_compile_file()する(Facebook方式)というのも手だけど、そこまでしたくないし、ファイル数が多いと現実的じゃないし*2、更新が頻繁にあるサイトだと苦しいし。
だったらonにしておけば良いかというとそうでもない。
ファイルの更新にrsync,svn upなどを使っている場合、キャッシュを消さないとどんどんメモリの使用量が増えてしまい、いつかexpungeが発生してしまう。
また、Smartyを使用していてコンパイルキャッシュをAPCでキャッシュしている場合も、テンプレートファイルを更新する度に*3メモリ使用量が増えてしまう。
折衷案としては、statはonにし、アクセスが少ない時間にapc_chache_clear()をGC代わりに実行するなど。
ちなみに、logrotateでApacheにHUPを送るとキャッシュがクリアされるよやったね!
onにする場合はshm_sizeに更なる余裕を。
APCの動作 2 キャッシュの削除
APCの動作 1 キャッシュの取得と生成
APCの動作について調べる必要があったので、調べた際のメモを公開。
今回はキャッシュの取得や格納部分について。元気があればキャッシュの削除等についても公開するかも。
設定によってどういった動作をするのかがメインなので、Opcode周辺には触れない。というかよくわからないので触れられない。
内容はAPC-3.0.14をLinuxで動かした場合を想定。
内容についてのツッコミ大歓迎。
初期化
- apc.num_files_hintはキャッシュされるファイル総数のヒント
- この値を2倍した数(num_slots)だけslot(1件のキャッシュをあらわすデータ)の領域が確保される
- ただし、この数がキャッシュ数の上限ではない
キャッシュの取得と生成の動作
- zend_compile_file関数を上書きしたmy_compile_file関数が呼ばれる
- apc_cache_make_file_key キャッシュ検索用にapc_cache_keyを作る関数
- stat=on
- stat=off
- apc_cache_find -> apc_cache_find_slot
- apc_cache_insert
メモ
- stat=onの場合はデバイスIDとinode番号でキャッシュを識別するため、例えばファイル名を変更してもinode番号が変わらなければ同じキャッシュを使い続ける事になる
- max_file_sizeはstat=offの場合無視されるっぽい
- PHPでrequireとかに渡すパスは絶対パスじゃないと相当遅くなる
- stat=offの場合はincludeパスを調べてくれないの?
- stat=onの場合ハッシュの計算方法は(デバイスID+inode番号)%num_slots
- TECHNOTES.txtによればrealpathを呼ぶと遅くなるのでinodeを使っていると書いてあるけど、なんでデバイスIDと足しているのか不明
- apc.num_files_hintが少なすぎる場合は微妙に遅くなる
- ttlに達したからといってそのキャッシュが使われなくなるわけではない
mod_auth_hmacのBeta版リリース
ちょっと前に、ようやくmod_auth_hmacのBeta版がリリースできた。
同時にプロジェクトホームページの内容も増やし、使用する上で必要となる最低限の情報は載せたつもり。
実はApacheのモジュール自体は4月頃から手を付けていなくて、クライアントのスクリプトとかドキュメントが一通り揃ったという事でBeta版にしたのだ。
クライアントスクリプトはPHPに加え、RubyとPython用のクラスも作ってみた。RubyもPythonもまとも(?)に書くのは初めてなので楽しい。RubyにはHMACを計算する標準的なクラスが無いらしいMacの1.8.2では見つからないので再発明。
時刻を表現する部分にUNIXタイムスタンプでは無くRFC 1123形式*1を使用しているのは、UNIXタイムスタンプをすぐには取得できない環境*2への優しさだったのだけど、Pythonにはどうやら逆効果だったみたいだ。
Pythonでタイムゾーンを扱う時はアプリケーションが責任を持って処理を行わなければならないらしく、ローカルの時刻からUTCに変換するのが少々面倒。ツンツン言語め。
SET NAMES
大垣さんのblogより
SET NEMESだと文字エンコーディングを利用したSQLインジェクションに脆弱となる可能性があります
http://blog.ohgaki.net/index.php/yohgaki/2007/06/05/php_5_2_3a_oa_oa_fa_s
工エエェ(略)
知らんかった…
SET NAMESを実行するとMySQLのサーバとクライアントでエスケープの処理が一致しなくなる場合があるという事だと思うけど、何でそんな仕様なんだろう。
おおっ
活発さ0%のmod_auth_hmacも小山さんのmod_auth_formを参考にさせてもらっているので、似てしまうのは当然といえば当然で、あっ、module.jpにつながらない!