最速の du を作ってみる

個人ブログはどれもこれも三日坊主な山本泰宇です。
チームブログはいいですね、誰かが日々記事を書いてくれるので、暇を見つけて自分も書こうという気になれます。

さて、今回はネタ記事です。タイトルからしてネタですよね。du というのはあるディレクトリ以下のディスク使用量を計算するプログラムなんですが、ディスクアクセスで律速される du に最速もくそもあるか!と。

それはわかってるんですが、「du 速くできない?」と言われたときに、ふと以下のようなことを考えてしまったんです。

  • Linux では readdir はライブラリコールなので、getdents 使うと少しいいかも
  • i-node 番号から直接ファイルサイズを求められれば、stat より速いかも

i-node 番号を直接指定できるシステムコールはないのですが、ext2/3/4 ファイルシステムなら debugfs コマンドでできるということが、Google で検索するとわかってしまいました。調べてみると debugfse2fslibs というライブラリを使っているようです。

 「なにそれ面白そう」と心の中で思ったならッ!
 その時スデに行動は終わっているんだッ!

というわけで思いついて家に帰ったその晩にはもう作ってしまっていました。orz
ソースは Gist で公開しています。

速くするために工夫したのは、以下のポイント:

  1. openat, fstatat で効率的にシステムコールを発行
  2. 内部ループでの malloc を極力回避
  3. getdents64 で大量に一括読み込み

さて。dentry と i-node がページキャッシュに載っているなら、このコマンドは通常の du の倍速いです。-DUSE_E2FSLIB の有無で e2fslibs を使って i-node から直接引くかどうか変えられるんですが、fstatat システムコールを使う通常版と何も変わりませんでした。

でも事前にわかっていた通り、dentry や i-node がキャッシュされていなければ、はるかに遅いディスク I/O がボトルネックになるのでこんなコマンドに意味はないのでした。おしまい。