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
      • type: APC_CACHE_KEY_FILE
      • path_translatedと与えられたファイルのパスが同一(URLに対応するファイル)の場合はサーバ(Apache)のstat結果を使用する
      • 同一ではないが絶対パスの場合はstatする
      • どちらでもない場合はincludeパスから探してstatする
      • max_file_sizeを超えないかのチェックもここでする
      • キャッシュの識別はデバイスIDとinode番号
    • stat=off
  • apc_cache_find -> apc_cache_find_slot
    • APC_CACHE_KEY_FILEの場合
      • (デバイスID+inode番号)%num_slotsでslotの配列からslotを取得する
    • APC_CACHE_KEY_FPFILEの場合
      • string_nhash_8(絶対パス)%num_slotsでslotを取得する
    • slotが探しているファイルのキャッシュかを調べる
      • APC_CACHE_KEY_FILEの場合
        • バイスIDとinode番号が一致するか
        • 更新日時が一致しない場合はキャッシュを削除
      • APC_CACHE_KEY_FPFILEの場合
    • 探しているファイルのキャッシュではない(衝突)場合は次のslotを調べる(slotはリンクリスト)
    • キャッシュが見つかった場合は処理を終了
    • キャッシュが見つからなかった場合は生成処理へ
  • apc_cache_insert
    • apc_cache_find_slotと同じ方法でslot取得
      • slotが見つかった場合
        • APC_CACHE_KEY_FILEの場合
          • バイスIDとinodeが一致すれば削除
          • 一致しなければttlに従い削除
        • APC_CACHE_KEY_FPFILEの場合
          • 絶対パスが一致すれば削除
          • 一致しなければttlに従い削除
    • キャッシュを生成しslotに格納

メモ

  • stat=onの場合はデバイスIDとinode番号でキャッシュを識別するため、例えばファイル名を変更してもinode番号が変わらなければ同じキャッシュを使い続ける事になる
    • 逆に言うと、ファイルパスが一緒でもinode番号が変われば別のキャッシュとして扱われる
      • rsyncsvn upはアトミックなファイル操作を行うため、更新されるファイルの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に達したからといってそのキャッシュが使われなくなるわけではない