clcacheを使ってVisualStudio2013のビルド(コンパイル)高速化

どーも。panjaです。

関西もだいぶ寒くなってきましたね。
体調を崩さないように手洗いうがいをしっかりしましょう。

さて、今回はccacheの亜種のclcacheについてです。

ccacheとは

まずはccacheについて。
ccache — Overview

Wikipediaさんによると、(ccache - Wikipedia)

ccacheとは、CまたはC++コンパイラが出力するデータをキャッシュするソフトウェア開発ツールである。その目的は、2回目以降のソフトウェアビルドにおいてはコンパイルを避け、出力結果を再利用することにある。これは再コンパイル速度を劇的に改善する。

ということです。
C、C++Objective-CObjective-C++に対応しています。
「遅いビルドは悪!」とレガシーコード改善ガイド(7.2章)にも記述があるように、なんとかビルドの高速化が出来ないかと思っていた矢先に出会いました。

しかし、、、こいつは普段VisualStudioで開発している私とは仲良くなれないやつだったのです。
VC++コンパイラcl.exeでは使えないとのことでした。(GCC系のコンパイラしか対応していない)


VC++で使えるやつないかー、と探して見つけたのが今回の本題clcacheです。

clcacheとは

ではclcacheについて書いていきます。
github.com

clchacheはGitHubで公開されているVC++用のコンパイラキャッシュです。

上記4つの情報を基にハッシュを生成して、2度目以降のコンパイル時の判定に使用しているようです。

GitHub上ではclcache.pyというpythonスクリプトファイルが公開されており、このファイルをpyinstallerを使ってexe化して使うというのが基本的な流れになります。

実際の流れは以下のような感じです。

(事前準備)
Python(ver3.3以上)をインストールしておく
・以下のコマンドでpyinstallerをインストールしておく

pip install pyinstaller


(手順)
1. GitHub - frerich/clcache: A compiler cache for MSVC, much like ccache for gcc から任意の場所にcloneしてくる(もしくはzipでダウンロードして展開する)
2. 以下のコマンドでclcache.pyの内容をexe化する(clcache.exeというファイルが./dist/以下に生成されます)

pyinstaller --onefile clcache.py

3. 任意の場所に(例えばC:¥clcache¥bin¥)にclcache.exeをコピーしcl.exeにリネームする
4. この場所にパスを通す(システム環境変数のPathの最初に追加)*2
5. 必要なら再起動する

以上で使えるようになっているはずです。
GitHub - frerich/clcache: A compiler cache for MSVC, much like ccache for gcc の「Installation for Visual Studio」という項目に別の方法が記載されていますが、私の場合はこの方法では上手くいきませんでした。環境によって結果は異なると思いますので注意してください。)

おもむろにVisualStudioを立ち上げてソリューションをリビルドしましょう。
1回目は今まで通り時間がかかります。





はい、終わりました。

適当に編集をして再度ビルドすると、、、


なんということでしょう~
すぐに終わりました(か?)

結果

ではどれくらい早くなったのか見てみましょう。

あるファイルを1行だけ改行させてビルドした結果です。
最適化手法によっても変わるのかな−と思ったので「最適化無効(/Od)」、「実行時間優先(/O2)」、「最大限の最適化(/Ox)」の3種類で試してみました。

clcacheを使わない場合はこんな感じでした。

最適化手法 コンパイル時間①*3 リンク時間*4 合計
無効(/Od) 40sec 80sec 120sec
実行時間優先(/O2) 40sec 110sec 150sec
最大限の最適化(/Ox) 37sec 110sec 147sec

はい。
コンパイルよりリンクに時間かかってますねぇ。。。。
今回はコンパイル時間を短縮するのが目的なのでこの問題はまた後で考えることにします。


clcacheを使った場合はこんな感じ。

最適化手法 コンパイル時間② リンク時間 合計 ②/①
無効(/Od) 22sec 74sec 96sec 0.55
実行時間優先(/O2) 36sec 100sec 136sec 0.9
最大限の最適化(/Ox) 37sec 98sec 135sec 1

はい。

なんだか微妙な結果です。
他のページに書いてあるような劇的な効果はありませんでした。
それどころか最大限の最適化を行った場合はあっても無くても同じという結果になりました。
まぁ最適化をしない場合には半分くらいにはなっているのでこの場合は有効と言えそうです。

まとめ

最適化を行わない場合はclcacheを使用してコンパイル時間が短くなることが確認できました。
ただ、他のページに紹介してあるような劇的な効果は今回は得られませんでした。

普段の開発ではclcacheを有効にしておいて、最適化は無効にしておくのが良さそうです。(もちろんリリース時に有効にする必要があります)
実験方法も悪いような気がしますし、継続的に効果を確認していきたいと思います。



リンク時間はどうやって短くできるんだろうか。。。

*1:The `normalized' command line

*2:本物のcl.exeをシステムが見つけてしまう前にこのcl.exeを見つけるための設定だと思います

*3:cl.exeが動いている時間を測りました

*4:link.exeが動いている時間を測りました