Hyperspace: ファイルを削除せずにディスク容量を節約するMacアプリ
(hypercritical.co)- Macの重複ファイル整理は通常、削除が前提だが、HyperspaceはAPFSクローンによって同じ内容のファイルを共有させ、ファイルを残したまま容量を取り戻す
- APFSのcopy-on-writeクローンは、Finderの「複製」のように実データを書き直さず元ファイルと共有するため、大容量の複製もほぼ瞬時に完了する
- 開発者はディスクがいっぱいになったことをきっかけに、内容は同じだがクローンではないファイルを見つけるPerlスクリプトを作成し、節約可能な容量が数十GBに達したことからアプリへ発展させた
- アプリは無料でダウンロードしてスキャンし、節約可能な容量を確認できるが、実際に容量を回収するには有料課金が必要
- 自分が作成または所有していないファイルを変更するためリスクは高いが、それだけ多くのMacユーザーに実用的な助けをもたらす可能性がある
APFSクローンでファイルを残したまま容量を回収
- Hyperspaceは、同じ内容を持つファイル同士がクローン関係にない場合、それらをAPFSクローンに変換してディスク上のデータコピーを1つだけ共有させる
- 既存のMac向け重複ファイルアプリはたいてい重複ファイルを見つけて削除することで容量を節約するが、Hyperspaceはファイルを削除せずに容量を回収する
- APFSの主要機能にはポイントインタイムスナップショットとcopy-on-writeクローンがある
- スナップショットはTime Machineバックアップをより安定的かつ効率的にするために使われる
- copy-on-writeクローンは、ディレクトリエントリとファイル内容のあいだにある柔軟な構造に基づいている
- Finderで「複製」コマンドを使ってファイルを複製すると、実際のファイル内容はコピーされず、元ファイルとデータを共有するクローンファイルが作られる
- この仕組みにより、ファイルサイズに関係なくFinderでの複製はほぼ瞬時に完了する
リリース方法と開発メモ
- 開発者は2024年末、自分のMacのディスクがいっぱいになったことをきっかけに、同じ内容を持つ非クローンファイルを探してクローンに変換するPerlスクリプトを書いた
- このスクリプトは、Cで書かれたコマンドラインツールとSwiftで書かれたコマンドラインツールを呼び出す
- 実行結果、節約可能な容量は数十GBと判明し、その後Macアプリへと発展した
- HyperspaceはMac App Storeで提供されている
- ダウンロードとスキャンは無料
- 実際の容量回収にはアプリ内課金が必要
- 詳細はHyperspace documentationで確認できる
- 開発面では、Hyperspaceは開発者にとって2本目のSwiftUI製Macアプリであり、SwiftUI life cycleを使った最初のアプリでもある
- Swift 6を使った2本目のアプリでもある
- 開発初期からSwift 6を使うほうが、すでにリリース済みのアプリをSwift 6へ移行するよりはるかに容易だった
- Swift 6にはまだ粗い部分が多く、今後の改善に期待している
- Hyperspaceは、HFS+からAPFSへの変換プロセスのように、アプリ自身が作成しておらず所有もしていないファイルを変更する
- 開発者はこれを自分が作ったアプリの中で最も危険なアプリと呼んでいる
- 同時に、最も多くの人にとって有用なアプリになる可能性があるとも考えている
1件のコメント
Hacker News の意見
以前、同じことをするコマンドラインユーティリティ
dedupを作ったことがあるドライランモードがあり、「賢く」最適なクローン元を選び、ハードリンクや他のクローンを理解し、メタデータを保持し、HFS 圧縮ファイルも正しく扱う
自分のデータはまだ壊したことがないが、ファイルシステム系ツールの常として、利用は自己責任
0 - https://github.com/ttkb-oss/dedup
Hyperspace は基本的に全ファイルをスキャンせず、許可リストにあるファイルだけを見ており、ファイル内容を理解する必要がある構造のように見える。エンドユーザーの立場ではテキストファイルとソースコードファイルの違いをどう区別しているのか分からず、デフォルトのスキャンでは 360MB だけが重複排除対象として見つかったが、全ファイルを許可すると 842MB に増えた
デフォルトでは 100KB 未満のファイルもスキャンせず、サイズ制限をオフにして全ファイルを許可すると 1.1GB まで増えた。全ファイル・サイズ制限なしの条件で、Hyperspace は 68,874 個中 67,309 個をスキャンし、
dedupは 67,426 個をスキャンしたHyperspace は 29,522 個のファイルが重複排除可能だとし、
dedupは 29,447 個を見つけた。すでに重複排除済みのファイルが 76 個あるので 1 個差が出ているが、正確な原因は分からないスキャン時間は Hyperspace が約 50 秒、
dedupが 14 秒だった。Hyperspace はファイルシステムをスキャンした後に重複計算を行い、その次に重複排除をするようだが、なぜ前の 2 段階を一緒にしないのか分からない。私はスキャン中にファイルシステムのメタデータをキューに入れ、並列で重複計算を始めるようにしており、大半はfts_readでディレクトリをたどる際に「タダで」得られるサイズ情報だけで不一致を弾けるHyperspace は 1.1GB 節約可能だとし、
dedupは 1.04GB と、すでに節約済みの 882MB を見つけた。Hyperspace を買うつもりはないので実際の重複排除時間やメタデータ保持、変なファイルの扱いまでは分からないが、dedupはスキャンと重複排除を合わせて 31 秒かかったdedupで重複排除した後でも、Hyperscan はまだ重複排除可能なファイルが 2 個あると判断した。Hyperspace も複数のハードリンクが張られたファイル、空ファイル、dedupが検査する各種例外は扱っているようだ。ACL やその他属性の保持は課金なしではテストできないが、stringsを見る限り処理しているように見え、HFS 圧縮は厄介な境界ケースなので、Hyperspace のスキャンがどう扱うかはまだ確認できていないプロジェクトにライセンスがないので、可能なら希望するライセンスを付けてもらえるとありがたい。インストール手順を少し改善しようとしてプルリクエストも作った: https://github.com/ttkb-oss/dedup/pull/6
特定のサブディレクトリだけを見ても、ある JS ファイル 50 個のコピーを 1 つに置き換えるようなことは珍しくなかった。ただし「pre-release」で GitHub のスターも少なめなので、こうしたツールはバグがあるとかなり怖いだけに、安定性が気になる
makeがほぼ即座に終わる点も印象的だった以前 https://github.com/sahib/rmlint を使っていたが、特に不満はなかった
「Hyperspaceが他のすべてのアプリやmacOS自体と協調して、ファイル置き換えに安全なタイミングを調整する方法もなく、そのファイルを強制的に排他的に制御する方法もない」という部分を見て、なぜファイルシステム自体がバックグラウンドで似たような重複排除プロセスを走らせないのか気になった
その程度の抽象化レイヤーなら、こうした安全性の問題を管理できそうに思えるが、APFS内部で自動的に起きるとどんな欠点があるのだろうとも思う
ファイルレベルで実装すればリソース使用量は減るかもしれないが、実装がより単純になるのか複雑になるのかは分からない。また、大きなファイルで1バイトだけ変更しても、ファイルシステムがそのファイルを再度複製しなければならず、ディスク活動が大量に発生するという点は直感的ではないかもしれない
このレイヤーで重複排除を行うと、複数のファイルシステムにまたがって重複排除できるので都合がよい。例えば、同じOSファイルを持つシステムが1000台あるならストレージ容量を大幅に節約でき、違いはホストキーやホスト名のようなシステムごとの設定程度であることが多い。単一のファイルシステムでは、こうした共通性に気付けない
ただし、重複排除によって使用頻度の高いファイルの複製数が減ると問題になる。先ほどの例で1000台を同時に起動すると、カーネルイメージにものすごいI/O負荷がかかる可能性がある
指定した範囲の集合をOSに丁重に重複排除してほしいと頼むと、OSが範囲をロックし、実際に同一かどうかを検証してから重複排除してくれる。各範囲で何バイトが重複排除されたかもフィールドとして返ってくるので、ユーザー空間のプログラムがファイルを壊す余地はない
Hyper-V VMを載せたReFSでかなり使ったことがあり、効果は抜群だった。当時はWindows Server 2016/2019が混在したVMが大半だったが、ストレージ使用量を約**45%**削減できた
スキャンは無料で行ってメリットがあるか確認し、実際の結果に対してだけ支払うモデルが気に入った
自分もファイルをため込みがちなので試してみたら、7GB回収可能と出たが、自分にとってはその程度では支払うほどではなかった。それでもこういうツールがあるのは良い
そもそも1か月に、まったく同じ重複ファイルをうっかりどれだけ作るというのか?
実際に頻繁に使う人向けにサブスクリプションや買い切りの選択肢もあるが、多くの人にとっては、限られた期間だけ使える一回限りのアプリ内課金がかなり合理的だ。そしていつでも無料で再実行して、また支払うほどたまったか確認できる
とてつもない量を作るわけではないが、一部または全部を合わせると大きな重複ファイルが生まれることがある。たいていは、ハードドライブの復旧結果を別の場所にあるファイルと突き合わせる必要があったり、散らかったダウンロードフォルダを整理済みの保存先と突き合わせる必要があったりする妙な状況で起きる
例えば、Time Machineバックアップが、自分では記録があることすら知らず、ずっと昔に失ったと思っていたファイルの古いバージョンを押し出してきたことがあるが、ディレクトリ名は壊れていて、内容もある程度難読化されていた。数字名のディレクトリが何千もあり、その中には保管したいファイルがあるかもしれないが、すでに持っているのか、どこにあるのかがまったく構造化されておらず分かりにくい。逆に、同じビルドシステムのテキストファイルが1つ入っているだけという場合も多く、そういうものは当然捨てられる
人々はすでにサブスクの罠に慣れすぎていて、これを新しいモデルのように感じているのだろうか
他のソフトウェアでもこうしやすければよいのだが、たいていは価値が見える前に学習曲線が立ちはだかっている
ちょっとしたコツとして、そういう体験版にはロックできるバーチャルカードを使うと、キャンセルを忘れても決済を防げる。ところで、Webサイトで実際のライセンス価格を見つけた人はいるのだろうか
アプリが2つのファイルが同一かどうかを判定するのに、どんなアルゴリズムを使っているのか気になる
ハッシュ、ビット単位の比較など興味深い方法は多いが、それぞれ欠点もある。ファイルが非常に多い場合、最良の方法は何だろう
各候補ファイルごとに、他の候補ファイルと同じか確認するための「キー」が必要だ。ファイルは数百万個あるかもしれないので、キーは小さく素早く生成できる必要があるが、同時に偽陽性があってはならない
今なら明らかな答えは、ファイル内容のSHA256ハッシュだ。非常に高速で、サイズも32バイトとそれほど大きくなく、偽陽性や衝突の確率は、実際に遭遇する前に世界が終わるほど低い。SHA256はこの用途では事実上の標準なので、別のことをしていたらかなり驚くだろう
ハッシュを重複排除に使う内容アドレス指定ファイルシステムで、ハッシュは書き込み時に計算されるため、性能コストが分散される
そうすれば大きなファイル全体をハッシュする必要がなく、同じハッシュを持つファイルだけを追加で見ればよい
AppleはAPFSのクローン機能を使えるように、
-cフラグをサポートする修正版の**cpコマンド**も同梱しているcpがそれをサポートしていないなら、Pythonから呼び出すこともできる例えば
import Foundation; Foundation.NSFileManager.defaultManager().copyItemAtPath_toPath_error_(...)のような形だファイルAが2か所にあり、これを実行した後で
A_0を変更した場合、A_1も一緒に変わるのか、それともA_0の新しい状態だけが実体化されてA_1はそのまま残るのかが気になるA_0を変更すると、書き込み時点でそのファイルのコピーを作成し、A_1には触れないhttps://en.wikipedia.org/wiki/Copy-on-write#In_computer_stor...
そのため
A_1はそのままにして、A_0の変更分用に新しいコピーを作ることになる。詳細は https://developer.apple.com/documentation/foundation/file_sy... を参照WWDC 2017でAppleがAPFSを発表する前、iOS 10.xアップデートの一部として、すべてのiPhoneを密かにAPFSへ試験的に変換し、その後HFS+へ戻していたというくだりが目を引いた
ファイルシステムの変更が失敗した場合、どうやって元に戻せるのかが気になる。コードを十分に検証することはできるだろうが、何か問題が起きたら取り消し不能に見える
Appleのテストマイグレーションでは、APFSスーパーブロックの作成まで含めて全体のマイグレーションを実行しつつ、HFS+スーパーブロックをAPFSスーパーブロックで恒久的に置き換えるコミットの直前で止めていた。戻すときは、生成されたAPFSスーパーブロックとメタデータブロックだけを「単に」片付ければよかった
本番環境でいろいろ壊してきた身としては、こんな大規模なマイグレーションを実行しろと言われたら、ボタンを押せるか分からない
[0] https://www.youtube.com/watch?v=IcyaadNy9Jk&t=1670s
オープンソースの世界にもextファイルシステムをbtrfsへ変換するツールがあり、(1) ロールバック可能で、(2) btrfsファイルシステムを使っている間も元のextファイルシステムをマウントできる
物語から始めて問題へと絞り込み、その解決策が問題を魔法のように解決する様子を見せている
優れたマーケティングの非常に良い例だ
巨大なNodeJSプロジェクトフォルダにかけてみたが、8.1GBのフォルダで1GBしか節約できないと表示された
ユーザーのホームフォルダまで含めて再実行したところ、731K個のファイル、127K個のフォルダ、2,755個の対象ファイルで、合計1.3GBの節約にとどまった。NodeJSフォルダだけを対象にしたときより300MB増えた程度だ
SystemとLibraryもスキャンしようとしたが、権限の問題で拒否された。パッケージマネージャーにpnpmを使っているので、すでにディスク使用量はほぼ最適に近いのだと思う
アイデアは素晴らしいが、現在の価格では正当化しにくく、月に1回程度バックグラウンドプロセスとして走る形ならよさそうだ
https://support.apple.com/guide/security/signed-system-volum...
比較バッファを減らすために導入したもののようだが、node_modules内のファイルがこのサイズ未満で、考慮されなかった可能性がある
同じ内容のファイルを ハードリンク に置き換える、似ているがより単純なスクリプトを作ったことがある
主な動機はPythonの仮想環境内のパッケージだった。似たようなパッケージをインストールしておくことが多く、バージョンが違っても多くのファイルはなお一致する。Numpy、PyTorch、TensorFlowのような一部のパッケージはかなり巨大なので、ディスク容量を相当に節約できた
https://github.com/albertz/system-tools/blob/master/bin/merg...
[1] https://en.wikipedia.org/wiki/Apple_File_System#Clones
poetry、hatch、pdmのような他のツールもそうだと思うが、細かい挙動はあまり使っていないのでよく分からない