'nix-collect-garbage'と'nix-store --gc'って一緒じゃないの?

はじめに

今年は​Rustと​Nixと​Ballerinaを​習得する​年にしようと​しているので、​Nixの​ドキュメントを​読み進めています。
チュートリアルを​読んでいるとnix-collect-garbageと​いう​コマンドが​目に​つきました。

普段nix-store --gcを​使ってましたが、nix-collect-garbageは​使った​ことがない。​見た​目と​しては​同じに​見えるけど、​どう​違うんだろう?と​思ったのが、​この​記事を​書いた​経緯です。

最初に​結論

どちらも​参照されていない​オブジェクトを​削除すると​いう​点は​同じだけど、nix-collect-garbageは​古い​世代を​削除する​オプションが​ある。​と​いう​ことでした。

以下は、​結論に​至るまでの​調査の​記録です。

nix-collect-garbageって​何?

nix-collect-garbageの​ドキュメントには​こう​書かれていました。

The command nix-collect-garbage is mostly an alias of nix-store —gc. That is, it deletes all unreachable store objects in the Nix store to clean up your system.

意訳:

基本的にはnix-store --gcと​同じで、​Nixストアの​使ってない​オブジェクトを​削除するよ。

違いと​しては、​以下の​説明が​ありました。

—delete-old and —delete-older-than, which also delete old profiles, allowing potentially more store objects to be deleted because profiles are also garbage collection roots. These options are the equivalent of running nix-env —delete-generations with various augments on multiple profiles, prior to running nix-collect-garbage (or just nix-store —gc) without any flags.

意訳:

--delete-old--delete-older-thanでは​古い​プロファイルを​削除した​あと、​nix-store —gcを​実行する

と​いう​ことは、​このような​関係性だな!と​理解しました。

nix-collect-garbage -> GC削除
nix-collect-garbage --delete-old -> 古い​世代削除 + GC削除

古い​世代を​削除できる​分nix-collect-garbageの​ほうが​沢山の​容量を​減らすことができそうだ。​と​いう​ことが​分かりました。

因みに、、

These options are the equivalent of running nix-env —delete-generations with various augments on multiple profiles, prior to running nix-collect-garbage (or just nix-store —gc) without any flags.

と​あるようにnix-env --delete-generationsと​いう​コマンドを​実行する​ことでも​同様な​ことができるようです。
似たような​ことできる​コマンドが​多くて​難しいね。

ところでnix-store --gcって​何?

折角なのでnix-store --gcに​ついても​ドキュメントを​確認してみました。

Without additional flags, the operation —gc performs a garbage collection on the Nix store. That is, all paths in the Nix store not reachable via file system references from a set of “roots”, are deleted.

意訳:

セットしたルートから​ファイルシステム経由で​参照できない​すべての​パスが​削除される

nix-collect-garbageの​ドキュメントと​同様に​参照できない​パスを​削除すると​いう​ことですね。

そこまでは​理解できましたが、​ルートって​どこだ?と​いう​疑問が​湧いたので​引き​続き​調べてみる​ことにしました。

ルートって​何?

The roots of the garbage collector are all store paths to which there are symlinks in the directory prefix/nix/var/nix/gcroots.

意訳:

/nix/var/nix/gcroots ディレクトリ配下に​ある​シンボリックリンクが​指している​ストアパス

ここまでの​話を​まとめると、nix-collect-garbageでは​引数を​指定する​ことで、​古い​世代を​削除できるそうです。​と​いう​ことは、​Nixでは​古い​世代に​紐付く​ストアパスは​永久に​削除されないと​いう​ことだろうか?
これも​調べてみた

Nixの​ガベージコレクションって​何?

どんぴしゃで​知りたいことが​書いて​あった。

Note however that as long as old generations reference a package, it will not be deleted. After all, we wouldn’t be able to do a rollback otherwise. So in order for garbage collection to be effective, you should also delete (some) old generations. Of course, this should only be done if you are certain that you will not need to roll back.

意訳:

古い​世代が​参照していると​削除しないよ。​ロールバックできなくなるからね

そらそうだよね。

おわりに

  1. gcrootsに​リンクが​ある​ものは​削除対象に​ならない
  2. 古い​世代も​gcrootsに​残っている
  3. だから、​古い​世代を​消さないと​削除対象に​ならない

と​いう​ことだった。

いままでnix-store --gcしか​実行してなかったので、​私の​PCには​古い​世代に​紐付く​オブジェクトが​残り続けているようだ。
たまには、nix-env --delete-generationsも​実行してみようと​思った。