hnwの日記

hardlink.pyを使ったらディスクの空き容量が劇的に増えた

ノートPCを使っているとディスクの空き容量が不足してくることがありますよね。僕の場合、$HOME/src/php以下にPHP 5.0.0から5.5.5まで88バージョンのPHPソースコードを展開しているのですが、このサイズが約8.9GiB、約110万ファイルと恐ろしい量であることがわかりました。


そこで、この全ファイルに対してhardlink.pyを適用してみたところ、7.7GiBほど空き容量が増えました。本稿ではこのhardlink.pyについて紹介します。

hardlink.pyとは

hardlink.pyは、同じファイルを見つけてhardlinkにしてくれるPythonスクリプトです。同じファイルが多ければ多いほどディスクの空き容量を節約できるというわけです。


同じファイルと見なす条件はオプション指定で変更できますが、僕は「ファイルの中身とオーナーとパーミッションが完全一致、ただしタイムスタンプは一致していなくてもよい」という条件でhardlink化しました。


このスクリプトは下記URLで配布されています。


活発にメンテナンスされている状況ではありませんが、一定の利用実績がありそうだったので、今回はこれを使ってみました。


もちろん、類似の他のツールを使ってもいいと思います。ざっくり調べたところでは、次のツールでも同じことが実現できそうです。

hardlink.pyのインストール

hardlink.pyは1ファイルなので、これをパスが通っている場所に置いて利用します。例えば次のようにすればよいでしょう。

$ cd $HOME/bin
$ wget https://hardlinkpy.googlecode.com/hg/hardlink.py
$ chmod 755 hardlink.py


もちろん、Mercurialリポジトリごと落としてきても構いません。

hardlink.pyの使用例

hardlink.pyを試してみた結果を紹介します。


最初に紹介したPHPソースコード群に対してhardlink.pyを適用してみました。コマンドラインではディレクトリだけを指定する必要がありますので、注意してください。

$ hardlink.py -t php-5.*
(略)
Directories           : 28446
Regular files         : 1099142
Comparisons           : 4342173
Hardlinked this run   : 1047194
Total hardlinks       : 1047194
Bytes saved this run  : 5261630979 (4.900 gibibytes)
Total bytes saved     : 5261630979 (4.900 gibibytes)
Total run time        : 4951.24222088 seconds
$


1時間20分ほどで110万ファイルの処理が終わりました。


上の出力を見ると約4.8GiBを節約できたように見えますが、これはhardlink化できたファイルサイズの総和のようで、正確な値ではありません*1。別途duした結果からすると、空き容量は約7.7GiB増えました。


また、約110万ファイルのうち、約105万ファイルがhardlink化できました。inode数も限りあるリソースですから、節約できるに越したことはありません。

まとめ

同内容のファイルが多い場合、hardlink.pyを使ってディスクの空き容量とinode数を節約できます。


今回の状況が非常に特殊に見えるかもしれませんが、開発環境で複数のブランチをデプロイする場合など、同じファイルが複数存在する状況は他にもあるはずです。


特に、こうしたファイル群をrsyncするような状況を考えると、事前にhardlink.pyでhardlinkを作っておいてからrsyncの--hard-linksオプションを利用することで、転送の総時間を高速化できる可能性があります。僕は実験していないのですが、デプロイスクリプトでの応用を試してみた方は是非結果を教えてください。



(11/17 19:40追記)ブックマークコメントでも指摘がありましたが、このようにhardlinkを作った場合にファイルを上書きしてしまうと予想外のパスのファイルの内容まで変わってしまう可能性が出てしまいます。上書きをしないようにしたり、いったんrmしてから新規作成するなり、運用には注意してください。

*1:このディスクは4096バイトブロックごとに管理されているため、1ファイルあたり平均2048バイトの無駄領域ができます