OS毎のシステムコール実行性能 〜 その3
前回までで fork
、vfork
および execve
といったプロセス生成系システムコールの実行性能を比較しましたので、今回はファイルシステム操作系システムコールの実行性能を比較しようと思います。
- その1: fork, execve の性能計測
- その2: vfork の性能計測
- その3: fstat, lstat の性能計測
- その4: getpid, gettimeofday の性能計測
- その5: time, umask の性能計測
- その6: まとめ
fstat の性能比較
確認用プログラムの手順は以下の様なものです。
- 引数指定のファイルを READONLY で
open
- 当該ファイルディスクリプタを使って
fstat
を実施 - 指定回数だけ
fstat
実施を繰り返し
fork
/execve
と比較した場合、fstat
の実行コストは随分低いですから、計測結果を安定させるために 0x4000000 =約6千7百万回の繰り返しで計測しました。
---- | MacOSX | Linux | Solaris |
---|---|---|---|
fstat | 31.12 | 8.36 | 62.13 |
lstat の性能比較
先述の fstat
は、あらかじめ open
で取得したファイルディスクリプタを使って実施されるため、ファイル名解決 (いわゆる "look up") のコストが計上されていません。
そこで今度は、ファイル名解決コストを含む lstat
の実行性能を計測してみましょう。
stat
の場合は、シンボリックリンクを辿る処理が含まれるため、lstat
を選択しました。まぁ、実際の実装上は、引き当てた実体に対して「リンクを辿るか否か」のフラグでロジックを切り替える程度のものでしょうから、あまり変わりは無いとは思いますが……
確認用プログラムの手順は、fstat
の代わりに lstat
を使用してる (+ 不要な open
は実施しない) 以外は、先述した fstat
性能計測用のものと同じです。
- 引数指定のファイルに対して
lstat
を実施 - 指定回数だけ
fstat
実施を繰り返し
こちらの計測でも、繰り返し回数は 0x4000000 =約6千7百万回です。
---- | MacOSX | Linux | Solaris |
---|---|---|---|
lstat | 51.18 | 27.41 | 165.26 |
fstat | 31.12 | 8.36 | 62.13 |
lstat - fstat | 20.06 | 19.05 | 103.13 |
Mac OS X と Linux の性能比が3倍以上あった fstat
に対して、lstat
は2倍弱程度にまで、性能差が縮んでいることがわかります。
上記の計測では、lstat
対象ファイルとして、「少数の要素しか持たないカレントディレクトリ直下のファイル」を指定しているので、fstat
と lstat
の差分は「ファイル名解決の (最小限の) コスト」とみなせる筈です。
ここで「ファイル名解決コスト」を見てみると、Mac OS X と Linux には 5% 程度の差しかありません。
lstat
における Mac OS X と Linux の性能差の大半は、fstat
相当処理 = 属性情報取得部分における性能差に起因していることになります。
但し、この結果は比較的浅いディレクトリ階層を対象にした場合の話であって、名前解決対象のディレクトリ階層が深くなった場合や、ディレクトリ配下の要素数次第では、この性能傾向が変わる可能性はあります。
ファイル数の増加や、ディレクトリ階層の増加による性能への影響に関しては、以前 Python Developers Festa 2013.11 で発表した、「Pythonista も ls を読むべきか?」と題したスライドも参照してみてください。
また、Mac OS X の標準ファイルシステムである HFS+ は、一致判定時に文字大小を無視 (case ignore) するのですが、その一方でディスクへの記録としては文字大小を保存 (case preserve) しているので:
- 比較時に都度 case ignore 比較を実施する → 実行時性能がよろしくない
- 保存時に、正規化 (全部大文字 or 小文字化) した情報を別途記録しておいて、比較にはそちらの情報を使用する → ディスク使用効率がよろしくない
といったトレードオフが発生します。
もしも、HFS+ が前者を選択していた場合は、一定規模以上のディレクトリツリーでは、性能劣化が顕著になる可能性もあります(この辺の HFS+ 実装の詳細をお知らせ頂けると助かります > 識者)。
Mercurial のテストセット全体では、stat
、lstat
、fstat
が合計千3百万回程度実行されていますので、上記計測における繰り返し回数 0x4000000 =約6千7百万の約2割程度とすれば、純粋に fstat
の実処理部分の性能差に由来する所要時間差は (31.12 - 8.36) * 0.2 = 4.55 秒程度と見込まれます。
この程度だと、「体感できる程度の所要時間差」の要因としては、弱そうですね。
後は、実際の局面における Mac OS X と Linux の名前解決処理の性能差次第、というところでしょうか?
ディレクトリ要素の追加・削除や、read
や write
などによる I/O 実施の性能差に関しては、CPU 以外の要素による影響が大きくなる (+ 本腰を入れて調べるのは非常に面倒w) ため、今回は踏み込みません。
以下、次回に続く。