emergeの高速化、もしくはメタデータキャッシュの話

eixはeix-updateで自前のキャッシュを作りますが、この時のソースがいくつか用意されています。

個別のebuildを直接読む(parse, ebuild
当然時間がかかります。また"ebuild"の場合はebuild(中身はシェルスクリプト)を実行するので、信用できないoverlayで使うべきでないとeixのmanには書かれていますね。
treeごとのキャッシュを使う(metadata-flat, metadata-md5, metadata-assign)
例えば/usr/portage/metadata/以下にあるやつです。gentooツリーの場合はこのキャッシュごと同期するので、ローカルで生成しなくても使えます。
emergeで生成するキャッシュを使う(flat, cdb, assign, sqlite, 多分repo-*も)
通常/var/cache/edb/dep/以下にあります。emerge --metadataなどで生成します。
eixのキャッシュファイルを使う(eix)
通常/var/cache/eix/以下にあります。

これはeixから見た話ですが、同じようなことをemergeでもしてるはず。
eixは何も考えなくても速いのでいいんですが、emergeはそのままだとなかなか依存解決に時間がかかるので速くしたいですね。
ということで色々比較。

環境

gentoo, local, gentoo-haskell, betagarden, sunriseが入ってます。
ちょうどhaskell-platformすら入っていない状態なので、emerge -p yesod-platformの時間を計ります。
ちなみにキャッシュ破棄した状態だとこんな感じ。

$ sudo rm -rf /var/cache/edb/dep
$ emerge -p yesod-platform
real    1m1.100s
user    1m24.869s
sys     0m18.156s

肝心のhaskell overlay以外も入ってるし、一回分のtimeそのままという適当さなのでほんとにざっくりですが。

emerge --metadata

emerge --syncしたときに勝手に走るようですが。eixから見たflatやassign。

$ sudo emerge --metadata
real    0m13.520s
user    0m12.737s
sys     0m0.760s

$ emerge -p yesod-platform
real    0m36.400s
user    0m27.230s
sys     0m5.042s

30秒って数字で見るとたいしたことなさそうですが、なかなか長く感じます。

md5-cache

treeごとのキャッシュのひとつで、gentooツリーでも使われています。eixから見たmetadata-md5
egencacheというコマンドで生成します。細かいことは後述。

$ sudo rm -rf /var/cache/edb/dep
$ sudo egencache --repo=gentoo-haskell --update --update-use-local-desc
real    1m22.179s
user    0m54.974s
sys     0m12.471s

$ emerge -p yesod-platform
real    0m28.985s
user    1m1.687s
sys     0m13.470s

--metadataだけと比べて、userはあまり変わってないもののrealが短くなってますね。
/var/lib/layman/haskell/metadata/md5-cache/ができています。
ここでさらに--metadata。

$ sudo emerge --metadata
real    0m19.451s
user    0m15.896s
sys     0m1.605s

$ emerge -p yesod-platform
real    0m4.473s
user    0m4.397s
sys     0m0.060s

速い。
試しに上で生成したgentoo-haskellのキャッシュを消してみましたが、変わりませんね。同じようにemerge --metadataを実行しても、元の形式によって変わるのでしょうか。。

sqlite

wiki.gentoo.orgができるまえのGentoo Wikiに記事があった方法です。
http://www.gentoo-wiki.info/TIP_speed_up_portage_with_sqlite
という時点でobsolete臭がするのですが、以前使っていた記憶があるのでこれも試してみます。

$ sudo vi /etc/portage/modules
$ sudo emerge --metadata
real    0m20.192s
user    0m17.771s
sys     0m2.379s

$ emerge -p yesod-platform
real    0m36.443s
user    0m27.226s
sys     0m5.068s

/var/cache/edb/dep/var/lib/layman/haskell.sqliteが生成されてはいますが・・・sqlite使わない場合とあまり変わりませんね。
md5-cacheと組み合わせてみましょう。

$ sudo egencache --repo=gentoo-haskell --update --update-use-local-desc
$ sudo rm -rf /var/cache/edb/dep
$ sudo emerge --metadata
real    0m21.745s
user    0m18.898s
sys     0m2.588s

$ emerge -p yesod-platform
real    0m4.701s
user    0m4.922s
sys     0m0.230s

これまたsqlite使わない場合と変わりませんね・・・。
eixのmanを見ると、portage-2.1以上でデフォルトのキャッシュがflatからassignに変更されているようです。flatの頃は今より遅く、cdbという非公式拡張や、今回試したsqliteなどが使われていた、というところでしょうか。

まとめ

大きなoverlayを使う場合はtreeごとのキャッシュを作ると良さそうです。というか、eixのmanにはSPEEDUPというセクションがあり、そういう話が書いてあります。自動で走らせる方法や注意点なども書いてあるので読みましょう、英語だけど。
ハウツー的なのをQiitaに書いたので読みたい方はこちらへ。
http://qiita.com/unarist@github/items/c1afa5ddfc7da1337b11

*1:ここには--regenを使った方法が書いてあるけど、--metadataでいいんじゃないかなあ。assign使うとしてもegencacheで変化するのは上に書いたとおり。