はじめに
今更ではあるがccacheの話である。ビルドする際の高速化を担うツールとしては有名であるが、調べてみると、古い情報しか見当たらない。
最近のFreeBSDでは指定方法が変わった、といったような情報が見当たらないので、今回、その点をメインに効果の程を解説する。
※従来と設定方法が変わって、極めて簡略に制御できるようになってます。
検証環境
- FreeBSD 13.0-RELEASE-p5
- FreeBSD 12.2-RELEASE-p11
ccacheのインストール手順そのものは今回は取り上げない(特別な手順は無い)。ただしディスク使用量調査のため、事前に下記のコマンドを実行して、キャッシュが効かなくなる状況を発生しないようにした。
結論から言えば、(FreeBSDのビルドだけなら)デフォルト使用量(5GB)でも問題無い。
ccache -M 32G
なお「バイト」のSI接頭辞は$10^3$を基本としているため、$2^{10}$にしたい場合は 32Gi
のような形で明示する必要がある(それでも表示は変更できない)。
また、数字だけの指定で単位を指定しない場合 G
として解釈される。
設定(/etc/src.conf)
WITH_CCACHE_BUILD= yes
ccacheを使用して buildworld
するだけなら、上記設定を行えばよい。環境変数 CC
に CC="ccache cc"
と設定するようなことはしなくてもよくなっている(ココ重要!)。
buildworld
あるいは buildkernel
時に必要あるいはコンパイル・インストール対象となるコンポーネントのオンオフについては src.conf(5) を参照すれば、一通り載っている、が、自分はまだ見逃しを確認していない(量多過ぎ…)。
make buildworld の実施
キャッシュが無い状態からの make buildworld
の実行を行った。キャッシュのヒット率等の情報を精査するために、buildworld
終了後に統計情報(ccache -s
コマンドの実行)を取得している。
一周目の実行結果
下記の通り、ほぼ全てのファイルのコンパイルが実施された。この時、CCACHEによるオーバーヘッドが発生することから、通常のコンパイル時間より長くなる。
また若干の再コンパイルが行われたが、高々0.2%も無いので無視していい。
cache directory /root/.ccache
primary config /root/.ccache/ccache.conf
secondary config (readonly) /usr/local/etc/ccache.conf
cache hit (direct) 5
cache hit (preprocessed) 77
cache miss 46123
cache hit rate 0.18 %
called for link 116
ccache internal error 1
unsupported code directive 3
no input file 1
cleanups performed 0
files in cache 137311
cache size 2.7 MB
max cache size 32.0 GB
また、実際のキャッシュ使用量が反映されないなど、一部参考にならない結果が得られる。これについては後述する。
二周目の実行結果
上記データ収集後、再度 buildworld
を実施した。下記の通りの結果が得られた。後述するが、キャッシュに100%ヒットした結果として「50.09%」の結果が得られている。
cache directory /root/.ccache
primary config /root/.ccache/ccache.conf
secondary config (readonly) /usr/local/etc/ccache.conf
cache hit (direct) 45050
cache hit (preprocessed) 1237
cache miss 46123
cache hit rate 50.09 %
called for link 232
ccache internal error 2
unsupported code directive 6
no input file 2
cleanups performed 0
files in cache 137454
cache size 2.7 MB
max cache size 32.0 GB
統計情報をゼロクリアしての三周目の実行結果
ccache -z
を実行して、再度 buildworld
を実施した。下記の通りの結果が得られる。二周目実行時にはわからなかった、「100%ヒット」が、確認できる。この時、一切コンパイルが行われていないため、buildworld
の実行時間が短縮されている。
cache directory /root/.ccache
primary config /root/.ccache/ccache.conf
secondary config (readonly) /usr/local/etc/ccache.conf
cache hit (direct) 45186
cache hit (preprocessed) 1019
cache miss 0
cache hit rate 100.00 %
called for link 116
ccache internal error 1
unsupported code directive 3
no input file 1
cleanups performed 0
files in cache 137578
cache size 2.7 MB
max cache size 32.0 GB
クリーンナップしてみる
キャッシュサイズが反映されない件について ccache -c
を実行して、統計データに反映させることができる。
cache directory /root/.ccache
primary config /root/.ccache/ccache.conf
secondary config (readonly) /usr/local/etc/ccache.conf
cache hit (direct) 45186
cache hit (preprocessed) 1019
cache miss 0
cache hit rate 100.00 %
called for link 116
ccache internal error 1
unsupported code directive 3
no input file 1
cleanups performed 0
files in cache 137578
cache size 4.5 GB
max cache size 32.0 GB
ご覧のように5GBでもギリギリ間に合うことが確認できる。
ベンチマーク
buildkernel の事例
karlさんから、下記の環境での make buildkernel
での計測結果をいただいたので表にまとめてみた。
- CPU: AMD Ryzen9 3900 (3.10GHz/4.30GHz)
- メモリ: 32GB
- ストレージ: WesternDigital SN550(NVMe接続)・ZFS運用
- ビルド対象: FreeBSD 14-CURRENT
ビルド手順 | CCACHE無し時間 | CCACHE有り時間 |
---|---|---|
make buildkernel |
1406秒 | 837秒 |
make -j4 buildkernel |
366秒 | - |
make -j8 buildkernel |
200秒 | - |
make -j12 buildkernel |
155秒 | 82秒 |
make -j16 buildkernel |
136秒 | - |
make -j20 buildkernel |
123秒 | - |
make -j24 buildkernel |
115秒 | 55秒 |
なお全CPUリソースを消費し切れなかったとのことでした。
buildworld の事例
- CPU: Intel Pentium N4200 (1.10GHz/2.50GHz・Apollo Lake/Goldmont アーキテクチャ)
- メモリ: 16GB
- ストレージ: Transcend MTS400S(SATA接続)・ZFS運用
- ビルド対象: 12.2-RELEASE-p11
ビルド手順※ | ビルド時間 |
---|---|
CCACHE無し | 22317秒 |
CCACHE有り(一周目) | 25603秒 |
CCACHE有り(二周目) | 3841秒 |
CCACHE有り(三周目) | 3854秒 |
※いずれも make -j5 buildworld
を指定
まとめ
- ビルド並列度(
-j
オプションの指定)の高低にかかわらず、100%キャッシュ時には数倍レベルの時間短縮効果(数分の一の時間でビルドが終る)が得られる。 - その効果もほぼC言語だけで構成された
buildkernel
の場合で2倍程度、LLVMのような重たいビルドを含むbuildworld
の場合は6倍程度の効果が確認できる。 - ccacheを導入した直後のオーバーヘッドは14%発生するが、二回目以降の効果を得るための代償としては誤差である。
- 少し修正しては全体をビルドしたいようなケース(開発等)での効果は非常に大きい。
- また今回、純粋に再ビルドするだけなら、100%コンパイルしないことも示した。これは
make clean
でオブジェクトが消えた状態でも確認している。 - 最近のFreeBSDでは、開発環境(LLVM)の構築に非常に時間がかかるようになったが、これが極めて短縮(時間的にもメモリ的にも)できる効果は大きい。
- とは言え、初回コンパイル時にメモリが必要となる点は変わらないので、少メモリ環境でのビルドは相変わらずつらいことには変わりない。
ccacheのの代表的なコマンド・オプション
ccache自体シンプルなせいか、あまりこの点について記載されているのを見ないため、簡単にまとめて見た。
コマンド | 意味 | 備考 |
---|---|---|
ccache -M n |
キャッシュ容量の設定(無指定の場合G ) |
最大キャッシュ容量を指定する※ |
ccache -s |
統計情報の表示 | |
ccache -z |
統計情報のクリア | |
ccache -c |
キャッシュディレクトリの精査 | クリーンナップ処理(キャッシュされたデータは削除しない) |
ccache -C |
キャッシュの削除 |
※n
に指定可能なサフィックスとしては「k
」「M
」「G
」「T
」「Ki
」「Mi
」「Gi
」「Ti
」が指定可能である。
よくある質問とその答え
Q./etc/make.conf に設定しちゃ駄目ですか?
A./etc/make.conf は必ず読まれるため、事実上 /etc/src.conf で設定したことと同じになります。その代わり、FreeBSDのビルド以外で設定が参照された場合、その振る舞いは保証されません。
その辺り気にしないのであれば設定しても問題ありません。同じ make
コマンドを参照する他のビルドと区別するために /etc/src.conf に設定するようにしましょう。