彷徨えるフジワラ

年がら年中さまよってます

OS毎のシステムコール実行性能 〜 その3

前回までで forkvfork および execve といったプロセス生成系システムコールの実行性能を比較しましたので、今回はファイルシステム操作系システムコールの実行性能を比較しようと思います。

fstat の性能比較

確認用プログラムの手順は以下の様なものです。

  1. 引数指定のファイルを READONLY で open
  2. 当該ファイルディスクリプタを使って fstat を実施
  3. 指定回数だけ fstat 実施を繰り返し

fork/execve と比較した場合、fstat の実行コストは随分低いですから、計測結果を安定させるために 0x4000000 =約6千7百万回の繰り返しで計測しました。

---- MacOSX Linux Solaris
fstat 31.12 8.36 62.13

Mac OS XLinux の性能比は、3倍以上になっています。

lstat の性能比較

先述の fstat は、あらかじめ open で取得したファイルディスクリプタを使って実施されるため、ファイル名解決 (いわゆる "look up") のコストが計上されていません。

そこで今度は、ファイル名解決コストを含む lstat の実行性能を計測してみましょう。

stat の場合は、シンボリックリンクを辿る処理が含まれるため、lstat を選択しました。まぁ、実際の実装上は、引き当てた実体に対して「リンクを辿るか否か」のフラグでロジックを切り替える程度のものでしょうから、あまり変わりは無いとは思いますが……

確認用プログラムの手順は、fstat の代わりに lstat を使用してる (+ 不要な open は実施しない) 以外は、先述した fstat 性能計測用のものと同じです。

  1. 引数指定のファイルに対して lstat を実施
  2. 指定回数だけ 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 XLinux の性能比が3倍以上あった fstat に対して、lstat は2倍弱程度にまで、性能差が縮んでいることがわかります。

上記の計測では、lstat 対象ファイルとして、「少数の要素しか持たないカレントディレクトリ直下のファイル」を指定しているので、fstatlstat の差分は「ファイル名解決の (最小限の) コスト」とみなせる筈です。

ここで「ファイル名解決コスト」を見てみると、Mac OS XLinux には 5% 程度の差しかありません。

lstat における Mac OS XLinux の性能差の大半は、fstat 相当処理 = 属性情報取得部分における性能差に起因していることになります。

但し、この結果は比較的浅いディレクトリ階層を対象にした場合の話であって、名前解決対象のディレクトリ階層が深くなった場合や、ディレクトリ配下の要素数次第では、この性能傾向が変わる可能性はあります。

ファイル数の増加や、ディレクトリ階層の増加による性能への影響に関しては、以前 Python Developers Festa 2013.11 で発表した、「Pythonista も ls を読むべきか?」と題したスライドも参照してみてください。

また、Mac OS X の標準ファイルシステムである HFS+ は、一致判定時に文字大小を無視 (case ignore) するのですが、その一方でディスクへの記録としては文字大小を保存 (case preserve) しているので:

  • 比較時に都度 case ignore 比較を実施する → 実行時性能がよろしくない
  • 保存時に、正規化 (全部大文字 or 小文字化) した情報を別途記録しておいて、比較にはそちらの情報を使用する → ディスク使用効率がよろしくない

といったトレードオフが発生します。

もしも、HFS+ が前者を選択していた場合は、一定規模以上のディレクトリツリーでは、性能劣化が顕著になる可能性もあります(この辺の HFS+ 実装の詳細をお知らせ頂けると助かります > 識者)。

Mercurial のテストセット全体では、statlstatfstat が合計千3百万回程度実行されていますので、上記計測における繰り返し回数 0x4000000 =約6千7百万の約2割程度とすれば、純粋に fstat の実処理部分の性能差に由来する所要時間差は (31.12 - 8.36) * 0.2 = 4.55 秒程度と見込まれます。

この程度だと、「体感できる程度の所要時間差」の要因としては、弱そうですね。

後は、実際の局面における Mac OS XLinux の名前解決処理の性能差次第、というところでしょうか?

ディレクトリ要素の追加・削除や、readwrite などによる I/O 実施の性能差に関しては、CPU 以外の要素による影響が大きくなる (+ 本腰を入れて調べるのは非常に面倒w) ため、今回は踏み込みません。

以下、次回に続く

備考

fstat および lstat 実行に関しては、Solaris は全く良い所が無い状況でした。

Linux はもちろん、Mac OS X と比べても、明らかに性能が劣っています。

Solaris カーネル野郎としては、改めて原因の所在を調査しておきたいところです。