BETA

findコマンドに複数のパスを指定すると何故遅いのか

投稿日:2018-10-15
最終更新:2018-10-24

findに複数のパスを指定する方はあまりいないと思う、普通はプロジェクトのルートを指定して全探索し絞り込みはgrepに任せる、それ単体で使えるgrep系の後発ツールに至っては一つしかパスを受け付けないものもある、ptとか。

遅いのを知った経緯

自分は特定のディレクトリ配下だけをfindにかける、という使い方をよくする、自作の連携ツールの関係上パスに複数のディレクトリや直接ファイルも指定する事があり、パス数が時には1000個にも及ぶ、その時に10秒以上の時間がかかっていた。その原因を探る為にfindコマンドのソースを読むと遅かった原因が分かった。

findの仕組み

findコマンドのソースコードを追っていく、findコマンドはfind系ユーティリティコマンド群findutilsの中の一つとなっている、GNUのfindutilsページからダウンロード出来る、バージョンは4.6.0。

ファイルサイズは大きいがfindコマンドはその中のfindディレクトリ、アプリロジックに絞ると750行ほどのftsfind.cだけを見ればよく、コア処理もその中の100行にも満たないfind関数である。

その中では検索対象であるパスをarglistに受け取り、ファイル階層をたどるFTS関数群に渡され、たどった結果を出力している。

static bool
find (char *arg)
{
  // ここに検索したいパスを指定する、
  // 末尾はNULLにする。
  char * arglist[2]; 

  ...

  // 引数で渡されたパスをセット
  arglist[0] = arg;
  arglist[1] = NULL;

このfind関数は指定されたパスの数分だけ実行される事になる、つまりは1000個のパスが指定されれば、FTS関数群にパスが渡されてディスクから一覧を検索し結果を取得して出力するという処理が1000回走る、これが遅い原因。

// find関数を呼び出している関数
static bool
process_all_startpoints (int argc, char *argv[])
{
  int i;

  /* figure out how many start points there are */
  for (i = 0; i < argc && !looks_like_expression (argv[i], true); i++)
    {
      state.starting_path_length = strlen (argv[i]); /* TODO: is this redundant? */
      if (!find (argv[i])) // ここが1000回呼ばれる
    return false;
    }

  if (i == 0)
    {
      /*
       * We use a temporary variable here because some actions modify
       * the path temporarily.  Hence if we use a string constant,
       * we get a coredump.  The best example of this is if we say
       * "find -printf %H" (note, not "find . -printf %H").
       */
      char defaultpath[2] = ".";
      return find (defaultpath);
    }
  return true;
}

複数のパスを指定しても遅くならないようにするには

実は簡単に解決できる、FTS関数群に複数パスを渡しちゃえばいい。 FTS関数群が受け取るarglistは末尾要素がNULLであれば複数のパスを指定できるので、find関数をパスの数分ループするのをやめてパス一覧を受け取ってfts_openに渡しちゃえば良い。

たったこれだけで、1000個のパスを渡したときに10秒かかっていた処理が0.2秒以内で終わるようになる。

おわりに

それをしたのがこちらです。

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

@wordijpの技術ブログ

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
or 外部アカウントではじめる
10秒で技術ブログが作れます!