2018年2月1日木曜日

RuboCopの起動が激遅になってしまったので何とかした話

RuboCop使ってますか?
Rubyでそれなりの規模のコード書くなら必ずと言っていいほど使いますよね。
僕はお仕事だとRailsを使っているのでRuboCopもガッツリ使っています。

最近RuboCopを実行しようとすると起動までがめっちゃ遅いっていう現象に悩まされていたんですよね。いったん動き出してしまえば普通なんですが。
bundle exec rubocop -Lとかして対象ファイルをリストアップするだけなのに4分とかかかるんです。

原因と解決方法を調べてみました。
原因はどうもRuboCopが検索するファイル数が多いと遅くなるってことのようです。
解決するには以下のような感じで除外ディレクトリを指定すれば良かったです。

AllCops:
  Exclude:
   - '.git/**/*'
    - 'public/**/*'
    - 'log/**/*'
    - 'tmp/**/*'

こんな感じにしたら4分かかっていたのが2秒以下になりました。劇的に改善してますね。
これで実行するのにストレスを感じずに済みそうです。

Railsのデフォルトで用意されるpubliclogtmpあたりのディレクトリは、通常はRubyコード置きませんしファイル数も多くなりがちなので除外しちゃうのが良いです。

そしてビックリすることにRuboCopは.gitディレクトリも検索対象に含んでしまうのです!

.gitt配下のファイルをRuboCopで処理したいことなんてないと思うのでデフォルトで除外してほしいところですよね。
※ちなみに2018/2/1現在の最新のRuboCop v0.52.1で確認してます。

普通は.gitディレクトリが含まれたくらいでそこまでファイル数増えないはずなので問題ないと思うのですが、git subtreeを使っていると話が変わってきます。
git subtree pushしたりすると.git/subtree-cacheにファイルが溜まります。

今の案件ではgit subtreeを結構使っていて、1万コミットくらいあるリポジトリでsubtree pushしたらsubtree pushするたびに.git/subtree-cacheに1万ファイルくらい増えているのを観測しました。僕の環境では200万ファイルくらい溜まっていました。

これがRuboCopが激遅になってしまった原因だったのです。まさかgit subtreeがRuboCopに影響するなんて思ってもみませんでした。
git subtree便利なんですが、ハマりどころも多くてまたかーって気持ちになりました。

まぁひとまずRuboCopの起動速度改善してよかったです。
これで快適なRuboCopライフが送れます。

2 件のコメント:

  1. こんにちは。
    記事を読んでデフォルトの修正を直すべきだなーと思ったので、直してみました。 https://github.com/bbatsov/rubocop/pull/5542
    次のリリースからは .git/ がデフォルトでExcludeされるようになります。

    とてもわかりやすいブログ記事をありがとうございました!

    返信削除
    返信
    1. コメントありがとうございます。

      たしかにRubocopのデフォルトの設定を修正すべきですね。英語を書くのが億劫でPRしていませんでした……。
      PRありがとうございました!

      削除