2012年2月20日月曜日

PHP FUSEのパフォーマンス計測(暫定)


PHP FUSEで、パススルーするだけのダミーファイルシステムを作ってみました。PHP FUSEを経由することによるオーバーヘッドを調べるべく、一応bonnie++でベンチしてみました。

■マウントオプション
allow_other,kernel_cacheを有効にしました。direct_ioを有効化するとシーケンシャルアクセスのブロックサイズが巨大化(4KB->120KB)して大幅に高速化(1.5倍速くらいに達するだろうか)するようですが、書き込み待ちや複数アクセス時のプチフリっぷりが気になったので、切りました。

■ベンチ結果まとめ
read/writeともに、ブロックサイズの大小によって挙動が大分変わるようです。シーケンシャルアクセスに関しては無視できる程度の影響であるようでした。CPUパワーは15%くらいでムンムン使っているものの、速度には影響せず。しかしブロックサイズが小さいとパフォーマンスダウンが激しいようです。特にseekの遅さの影響をモロに受けているようです。現状read&writeの度にfseekを発行しているんで、前回のoffset情報をもとに要不要を判定して余分なfseekを抑制すると、速くなったりしないかな? また今度やってみよう。

■具体的な結果:NFSマウント(From:CentOS5.7 DomU on CentOS5.7 / To:OpenIndianaのZFS)
Version  1.96       ------Sequential Output------ --Sequential Input- --Random-
Concurrency   1     -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
toreteru-dev-www 2G   575  98 33267   3 21715   4   835  99 40707   1  8868 175
Latency             29500us   20753ms   10807ms   19498us     438ms   83160us
Version  1.96       ------Sequential Create------ --------Random Create--------
toreteru-dev-www01. -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
              files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                 16    25   0  2650   1    48   0    25   0  2923   0    50   0
Latency               422ms   36661us     647ms     529ms    7140us     352ms

■具体的な結果:PHP FUSE経由でスルーパスしたもの(現実的なエラー対策とか講じてますけど)
Version  1.96       ------Sequential Output------ --Sequential Input- --Random-
Concurrency   1     -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
toreteru-dev-www 2G    13   5 33111   3 13880   1   763  97 37051   2  2205  12
Latency              1502ms    9371ms    6478ms   26108us     534ms   54831us
Version  1.96       ------Sequential Create------ --------Random Create--------
toreteru-dev-www01. -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
              files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                 16    23   0  1842   1    49   0    24   0  1879   0    49   0
Latency               499ms    2074us    5770ms     429ms   10118us     282ms

■備考メモ
実装上、最大のハマりどころは、getattrで32bit超えの値を返すとPHP FUSEの中でオーバーフローしてしまう件。これは前エントリの通り強引にパッチ当てで解消しました。

次なるハマりどころは、mknod関数の実装じゃないでしょうか。パススルーしようにも、PHPにはそのものジャストのmknod関数が存在せず。posix_mknodなる聞き慣れない関数でお茶を濁しましたが、使い方が合ってるのか、よくわかりません。引数がメジャーとマイナーに分かれてる件は、PHP FUSEから渡されてきたバイト列を上位下位で2等分して渡せばいいのかなと勝手に解釈。動いてるし、FIFOとか使わないから、まぁいいや。ファイルシステム周りはシステムコールが使えないといろいろ不安ですね。

その次のポイントは、openの実装でしょうか。read&writeのたびにfopenしてると途轍もなく遅いので、openでfopenしたファイルハンドルをメンバ変数配列で保持&ファイルディスクリプタ番号を自前で生成して返却(3〜255)、releaseでfclose、writeとreadとreleaseはpathは無視してファイルディスクリプタ番号を元にメンバ変数で保持したファイルハンドルを特定して作業するって寸法で実装しました。ファイルディスクリプタ番号は有限なので、空き番号を管理する仕組みも入れておきました。

Linux開発の本を読んでおいてよかったなぁ。

0 件のコメント: