彷徨えるフジワラ

年がら年中さまよってます

Python の構成管理ツールを Mercurial に移行

mercurial-ja でも話題を振ったけど、一応こちらでも。

Python 自身の開発に使用する構成管理ツールを、Mercurial に移行することが決定(英語)した模様。

決定の過程に関する詳細は、http://www.python.org/dev/peps/pep-0374/(英語) などからみることが可能。
上記の選出過程詳細における Tests/Impressions を見ると結構面白くて:

VCS San Francisco Vancouver Space
svn 1:04 2:59 139 M
hg 2:30 5:24 171 M
git 2:54 5:28 134 M

上記テーブルは、Python リポジトリからの clone(checkout) に要する時間/ディスク消費なのだけど、全履歴情報を保持している筈の git が、Mercurial どころか svn よりもディスク消費量が少ない!

Mercurial に比べて耐障害性が高い」理由が「差分保持じゃなくて、リビジョン毎の全スナップショット保持」だった筈なのに、その上でディスク消費が少ないっておかしくない?という疑問は、その先に書かれている『履歴表示』や『特定リビジョンへの update』の所要時間を見れば氷解。

おそらく猛烈に圧縮してあるんだね。clone で git の所要時間が多いのも圧縮処理に時間を要しているのかな。
※ 2014/01/28 追記
選定時の評価対象となった Git 1.6.1 の時点で、履歴データを単一ファイル化する pack 形式が導入されているので、単純な「データ圧縮率」ではなく、以下のような理由により、ディスク消費量が少なくなっているのだと思われます。

Git の checkout 性能が低いのは、pack 形式からのデータ取り出し自体(and/or 差分記録された場合の必要なデータの展開)がコスト高なのかもしれません。

ちなみに、ファイルの初期追加で Git/Mercurial の単一データ圧縮を比較したところ、Git よりもむしろ Mercurial の方が若干データ圧縮率が高めでした。

pack 時における共通データ部分の共有

Git の pack 形式では、類似性の高いファイルを記録する際に、元データ+差分の形態で記録されるため、ディスク消費量が低減される模様です。

pack 形式化は、明示的な git gc 実行をはじめとする garbage collection 契機で実施されるため、pack 化される前の状態だと、ディスク消費の傾向が変わる可能性もあります。

Mercurial の場合、履歴情報記録において、ファイル内容をファイル横断で共有するようなことが無い為、内容が同じ/類似性が高いファイルが多数あるようなケースでは、ディスク消費量の差が、より顕著になるかもしれません。

単一 pack ファイル化による、ブロック消費量の削減

Mercurialリポジトリでは、個々のファイル内容の変遷は、記録先がファイル毎に分かれています。そのため、HDD の消費ブロック数ベースでのリポジトリサイズは、本来のデータサイズ以上に上振れする傾向があります(データサイズ << ブロック消費)。

例えば、Linuxext3 ファイルシステムのデフォルトでは、ブロック割り当て単位は 4096 バイトです。つまり、10 バイトのファイルでも、4095 バイトのファイルでも、消費ブロック数ベースでは 4096 バイト分だけ消費することになります。

その一方、履歴が pack 化(= 単一ファイル化)された Git リポジトリでは、そういった上振れ分がありません(データサイズ ≒ ブロック消費)。

仮に、個々のファイルで見れば僅かな誤差しかなかったとしても、一定以上の規模(= 管理対象ファイル)を持つリポジトリの場合、データサイズとブロック消費の乖離は、無視できない量になる可能性があります。