重複排除ワープスピードの高度な読み取り専用ファイルシステム。
Linux および Windows 用の高速高圧縮読み取り専用ファイル システム。
DwarFS は、特に冗長性の高いデータに対して非常に高い圧縮率を達成することに重点を置いた読み取り専用ファイル システムです。
冗長であれば適切に圧縮されるはずなので、これはおそらくあまり魅力的ではないように思えます。ただし、他の読み取り専用の圧縮ファイル システムでは、この冗長性をうまく活用できないことがわかりました。他の圧縮ファイルシステムとの比較については、こちらをご覧ください。
DwarFS は速度に関しても妥協せず、私のユースケースでは SquashFS と同等か、それよりも優れたパフォーマンスを発揮することがわかりました。私の主な使用例では、 DwarFS 圧縮は SquashFS 圧縮よりも 1 桁優れており、ファイル システムの構築が 6 倍速く、通常は DwarFS 上のファイルへのアクセスが速く、CPU リソースの使用量も少なくなります。
DwarFS の機能を理解するために、合計サイズ 39 GiB のビデオ ファイルのセットにおける DwarFS と SquashFS の簡単な比較を次に示します。ユニークな点は、それぞれの固有のビデオ ファイルに、異なるオーディオ ストリームのセットを持つ 2 つの兄弟ファイルがあることです (これは実際の使用例です)。したがって、ビデオ データとオーディオ データの両方に冗長性がありますが、ストリームがインターリーブされており、同一のブロックが通常非常に離れているため、その冗長性を圧縮に利用するのは困難です。 SquashFS は基本的にソース データの圧縮にまったく失敗しますが、DwarFS はサイズを理論上の最大値に近いほぼ 3 分の 1 に削減できます。
$ du -hs dwarfs-video-test
39G dwarfs-video-test
$ ls -lh dwarfs-video-test.*fs
-rw-r--r-- 1 mhx users 14G Jul 2 13:01 dwarfs-video-test.dwarfs
-rw-r--r-- 1 mhx users 39G Jul 12 09:41 dwarfs-video-test.squashfs
さらに、SquashFS イメージをマウントし、fio-3.34 を使用してランダム読み取りスループット テストを実行すると、 squashfuse
とsquashfuse_ll
の両方が約 230 MiB/s で最高になります。
$ fio --readonly --rw=randread --name=randread --bs=64k --direct=1
--opendir=mnt --numjobs=4 --ioengine=libaio --iodepth=32
--group_reporting --runtime=60 --time_based
[...]
READ: bw=230MiB/s (241MB/s), 230MiB/s-230MiB/s (241MB/s-241MB/s), io=13.5GiB (14.5GB), run=60004-60004msec
比較すると、DwarFS は20 GiB/s のランダム読み取り速度を維持できます。
READ: bw=20.2GiB/s (21.7GB/s), 20.2GiB/s-20.2GiB/s (21.7GB/s-21.7GB/s), io=1212GiB (1301GB), run=60001-60001msec
DwarFS の特徴は次のとおりです。
類似性ハッシュ関数を使用した類似性によるファイルのクラスタリング。これにより、ファイル境界を越えた冗長性を利用することが容易になります。
非圧縮ファイル システムのサイズを削減するための、ファイル システム ブロック全体のセグメンテーション分析。これにより、圧縮ファイル システムを使用するときにメモリが節約され、より多くのデータをキャッシュに保持できるため、潜在的にキャッシュ ヒット率が向上します。
ファイルまたはファイルの断片を分類し、個々のカテゴリを異なる方法で処理するための分類フレームワーク。たとえば、これにより、非圧縮ファイルの圧縮や FLAC 圧縮を使用した PCM オーディオ データの圧縮に時間を無駄にすることがなくなります。
高度なマルチスレッド実装。ファイル システム作成ツールと FUSE ドライバーはどちらも、システムの多くのコアを有効に活用できます。
私は 2013 年に DwarFS に取り組み始めました。私の主な使用例と主な動機は、数百の異なるバージョンの Perl があり、約 30 ギガバイトのディスク領域を占有しており、労力の 10% 以上を費やすのは忍びなかったということでした。たまたま必要になったときのために、ドライブに保管しておきます。
それまでは扱いやすいサイズに絞るためにCromfsを使っていました。しかし、ファイルシステム イメージの構築にかかる時間にますますイライラするようになり、さらに悪いことに、約 1 時間ほどでクラッシュすることが多くなりました。
もちろん SquashFS も調べましたが、Cromfs の圧縮率に近づくことはできませんでした。
これだけでは DwarFS を書くのに十分ではありませんでしたが、同時に、私は最近の開発と新しい C++ 標準の機能にかなり夢中になっていて、C++ の趣味のプロジェクトに取り組むことを本当に望んでいたのです。あと、FUSEを使って何かやりたいとずっと思っていました。最後になりましたが、私は圧縮ファイル システムの問題について少し考えていて、ぜひ試してみたいアイデアがいくつかありました。
コードの大部分は 2013 年に書かれたもので、その後、いくつかのクリーンアップ、バグ修正、リファクタリングを時々行いましたが、リリースしても満足できる状態には決して到達しませんでした。 Facebook の (非常に素晴らしい) Folly ライブラリに依存して構築するのはあまりにもぎこちなく、ドキュメントもありませんでした。
今年もこのプロジェクトを掘り起こしてみると、事態は以前ほど厳しいものではないようでした。 Folly は CMake でビルドされるようになったので、サブモジュールとして取り込んだだけです。他のほとんどの依存関係は、広く入手できるパッケージから満たすことができます。初歩的なドキュメントもいくつか書きました。
DwarFS は通常、最小限の変更をそのまま使用するだけで問題なく構築できます。そうでない場合は、問題を報告してください。最新の依存関係のセットを決定するのに役立つ、Ubuntu (22.04 および 24.04)、Fedora Rawhide、および Arch の Docker イメージを使用して CI ジョブをセットアップしました。リリース tarball からビルドする場合は、git リポジトリからビルドする場合よりも必要な依存関係が少ないことに注意してください。特に、リリース tarball からビルドする場合は、 ronn
ツール、Python、 mistletoe
Python モジュールは必要ありません。
注意すべき点がいくつかあります。
サブモジュールとして含まれ、DwarFS とともに構築される folly ライブラリと fbthrift ライブラリをバンドル解除しようとする傾向があります。私もその意見には同意しますが、残念ながらそれは悪い考えです。 folly は ABI の安定性について何ら主張していないという事実 (つまり、あるバージョンの folly に対してビルドされたバイナリを別のバージョンに対して動的にリンクすることはできません) に加えて、別のコンパイルでビルドされた folly ライブラリに対して安全にリンクすることさえ不可能です。オプション。 C++ 標準バージョンなどの微妙な違いでも、実行時エラーが発生する可能性があります。詳細については、この号を参照してください。現在、DwarFS は両方のライブラリの最小限のサブセットを構築しているため、folly/fbthrift の外部バージョンを使用することさえできません。これらはdwarfs_common
ライブラリにバンドルされており、厳密に内部で使用されます。つまり、DwarFS のライブラリに対してビルドするために folly ヘッダーや fbthrift ヘッダーは必要ありません。
システムにインストールされたバージョンの GoogleTest を使用する場合にも、同様の問題が発生する可能性があります。 GoogleTest 自体は、ビルドの一部としてダウンロードすることを推奨しています。ただし、 cmake
呼び出しに-DPREFER_SYSTEM_GTEST=ON
を渡すことで、システムにインストールされたバージョンを使用できます。ご自身の責任でご使用ください。
他のバンドルされたライブラリ (つまり、 fmt
、 parallel-hashmap
、 range-v3
) の場合は、最低限必要なバージョンを満たしている限り、システムにインストールされているバージョンが使用されます。それ以外の場合は、ビルド中に優先バージョンがフェッチされます。
各リリースには、ダウンロード可能なLinux-x86_64
、 Linux-aarch64
、およびWindows-AMD64
用の事前構築済みの静的にリンクされたバイナリが含まれています。これらは依存関係なしで実行できるはずであり、ソースからツールを簡単に構築できない古いディストリビューションでは特に役立ちます。
バイナリ tarball に加えて、各アーキテクチャで使用できるユニバーサル バイナリもあります。これらのユニバーサル バイナリには、すべてのツール ( mkdwarfs
、 dwarfsck
、 dwarfsextract
、およびdwarfs
FUSE ドライバー) が 1 つの実行可能ファイルに含まれています。これらの実行可能ファイルは upx を使用して圧縮されるため、個々のツールを組み合わせたものよりもはるかに小さくなります。ただし、バイナリを実行するたびに解凍する必要があることも意味し、かなりのオーバーヘッドが発生する可能性があります。それが問題になる場合は、「クラシック」個別バイナリを使用するか、ユニバーサル バイナリを解凍することができます。例:
upx -d dwarfs-universal-0.7.0-Linux-aarch64
ユニバーサル バイナリは、適切なツールにちなんで名付けられたシンボリック リンクを通じて実行できます。例えば:
$ ln -s dwarfs-universal-0.7.0-Linux-aarch64 mkdwarfs
$ ./mkdwarfs --help
ファイル システムがシンボリック リンクをサポートしている場合、これは Windows でも機能します。
> mklink mkdwarfs.exe dwarfs-universal-0.7.0-Windows-AMD64.exe
> .mkdwarfs.exe --help
あるいは、コマンド ラインの最初の引数として--tool=<name>
を渡してツールを選択することもできます。
> .dwarfs-universal-0.7.0-Windows-AMD64.exe --tool=mkdwarfs --help
dwarfs.exe
Windows バイナリと同様に、ユニバーサル Windows バイナリは WinFsp プロジェクトのwinfsp-x64.dll
に依存していることに注意してください。ただし、ユニバーサル バイナリの場合、DLL は遅延ロードされるため、DLL がなくても他のすべてのツールを使用できます。詳細については、「Windows サポート」セクションを参照してください。
DwarFS はビルド ツールとして CMake を使用します。
Boost と Folly の両方を使用しますが、後者は実際にパッケージを提供しているディストリビューションがほとんどないため、サブモジュールとして含まれています。 Folly 自体には多くの依存関係があるため、最新のリストについてはここで確認してください。
また、Facebook Thrift、特にfrozen
ライブラリを使用して、スペース効率が高く、メモリ マッピングが可能で明確に定義された形式でメタデータを保存します。これはサブモジュールとしても含まれており、コンパイラと、DwarFS が動作するのに十分な量を含む非常に縮小されたライブラリのみを構築します。
それ以外では、DwarFS は実際には FUSE3 と、Folly がすでに依存している一連の圧縮ライブラリ (つまり、lz4、zstd、liblzma) にのみ依存しています。
テストを使用してビルドすると、googletest への依存関係が自動的に解決されます。
apt ベースのシステムの良い出発点は、おそらく次のとおりです。
$ apt install
gcc
g++
clang
git
ccache
ninja-build
cmake
make
bison
flex
fuse3
pkg-config
binutils-dev
libacl1-dev
libarchive-dev
libbenchmark-dev
libboost-chrono-dev
libboost-context-dev
libboost-filesystem-dev
libboost-iostreams-dev
libboost-program-options-dev
libboost-regex-dev
libboost-system-dev
libboost-thread-dev
libbrotli-dev
libevent-dev
libhowardhinnant-date-dev
libjemalloc-dev
libdouble-conversion-dev
libiberty-dev
liblz4-dev
liblzma-dev
libzstd-dev
libxxhash-dev
libmagic-dev
libparallel-hashmap-dev
librange-v3-dev
libssl-dev
libunwind-dev
libdwarf-dev
libelf-dev
libfmt-dev
libfuse3-dev
libgoogle-glog-dev
libutfcpp-dev
libflac++-dev
nlohmann-json3-dev
gcc
を使用してビルドする場合、最適化レベルはリリース ビルドの CMake デフォルトの-O3
ではなく-O2
に設定されることに注意してください。少なくともgcc-10
までのバージョンでは、 -O3
ビルドは-O2
を使用したビルドより最大 70% 遅くなります。
まず、リリース アーカイブを解凍します。
$ tar xvf dwarfs-x.y.z.tar.xz
$ cd dwarfs-x.y.z
あるいは、git リポジトリのクローンを作成することもできますが、これにはより多くの依存関係があり、リポジトリからビルドするときに生成する必要がある自動生成ファイルのほとんどがリリース アーカイブに同梱されているため、ビルドに時間がかかる可能性が高いことに注意してください。
$ git clone --recurse-submodules https://github.com/mhx/dwarfs
$ cd dwarfs
すべての依存関係がインストールされたら、以下を使用して DwarFS を構築できます。
$ mkdir build
$ cd build
$ cmake .. -GNinja -DWITH_TESTS=ON
$ ninja
その後、以下を使用してテストを実行できます。
$ ctest -j
すべてのバイナリは、デフォルトでメモリ アロケータとして jemalloc を使用します。これは、通常、 glibc
またはtcmalloc
アロケータと比較して使用するシステム メモリがはるかに少ないためです。 jemalloc
の使用を無効にするには、 cmake
コマンド ラインで-DUSE_JEMALLOC=0
を渡します。
DwarFS ライブラリ、ツール、および FUSE ドライバーを個別にビルド/インストールすることもできます。これは、DwarFS をパッケージ化するときに最も興味深いものです。ツールと FUSE ドライバーでは、ライブラリがビルドされているか、すでにインストールされている必要があることに注意してください。ライブラリのみを構築するには、次を使用します。
$ cmake .. -GNinja -DWITH_TESTS=ON -DWITH_LIBDWARFS=ON -DWITH_TOOLS=OFF -DWITH_FUSE_DRIVER=OFF
ライブラリがテストされインストールされたら、以下を使用してツール (つまり、 mkdwarfs
、 dwarfsck
、 dwarfsextract
) を構築できます。
$ cmake .. -GNinja -DWITH_TESTS=ON -DWITH_LIBDWARFS=OFF -DWITH_TOOLS=ON -DWITH_FUSE_DRIVER=OFF
FUSE ドライバーをビルドするには、以下を使用します。
$ cmake .. -GNinja -DWITH_TESTS=ON -DWITH_LIBDWARFS=OFF -DWITH_TOOLS=OFF -DWITH_FUSE_DRIVER=ON
インストールは次のように簡単です。
$ sudo ninja install
ただし、遊ぶためにツールをインストールする必要はありません。
静的にリンクされたバイナリを構築しようとすることは強く推奨されず、公式にはサポートされていません。そうは言っても、静的バイナリを構築できる環境をセットアップする方法は次のとおりです。
これはubuntu-22.04-live-server-amd64.iso
でテストされています。まず、上記の依存関係としてリストされているすべてのパッケージをインストールします。以下もインストールします。
$ apt install ccache ninja libacl1-dev
ccache
とninja
はオプションですが、高速なコンパイルに役立ちます。
ディストリビューションに応じて、いくつかのライブラリ (Ubuntu のlibarchive
やlibmagic
など) の静的バージョンをビルドしてインストールする必要があります。
$ wget https://github.com/libarchive/libarchive/releases/download/v3.6.2/libarchive-3.6.2.tar.xz
$ tar xf libarchive-3.6.2.tar.xz && cd libarchive-3.6.2
$ ./configure --prefix=/opt/static-libs --without-iconv --without-xml2 --without-expat
$ make && sudo make install
$ wget ftp://ftp.astron.com/pub/file/file-5.44.tar.gz
$ tar xf file-5.44.tar.gz && cd file-5.44
$ ./configure --prefix=/opt/static-libs --enable-static=yes --enable-shared=no
$ make && make install
それでおしまい!これで、DwarFS の静的バイナリの構築を試すことができます。
$ git clone --recurse-submodules https://github.com/mhx/dwarfs
$ cd dwarfs && mkdir build && cd build
$ cmake .. -GNinja -DWITH_TESTS=ON -DSTATIC_BUILD_DO_NOT_USE=ON
-DSTATIC_BUILD_EXTRA_PREFIX=/opt/static-libs
$ ninja
$ ninja test
mkdwarfs、dwarfs、dwarfsck、および dwarfsextract のマニュアル ページを確認してください。各バイナリに--man
オプションを使用してマニュアル ページにアクセスすることもできます。例:
$ mkdwarfs --man
dwarfs のマニュアル ページには、読み取り専用の DwarFS イメージ上に書き込み可能なファイル システム マウントを作成するために、overlayfs を使用して DwarFS をセットアップする例も示されています。
DwarFS ファイルシステム形式の説明は、dwarfs-format にあります。
mkdwarfs
の内部動作の概要をこのシーケンス図に示します。
CMake を使用してプロジェクトをビルドしている場合、DwarFS ライブラリの使用は非常に簡単です。簡単に始めたい場合は、ライブラリを使用して DwarFS イメージに関する情報を出力したり ( dwarfsck
など)、またはそれを抽出したり ( dwarfsextract
など) するコード例を見てください。
個別のライブラリは 5 つあります。
dwarfs_common
には、他のすべてのライブラリに必要な共通コードが含まれています。インターフェースはdwarfs/
で定義されます。
dwarfs_reader
DwarFS イメージからデータを読み取るために必要なすべてのコードが含まれています。インターフェースはdwarfs/reader/
で定義されます。
dwarfs_extractor
libarchive
を使用して DwarFS イメージを抽出するために必要な ccode が含まれています。インターフェースはdwarfs/utility/filesystem_extractor.h
で定義されています。
dwarfs_writer
DwarFS イメージの作成に必要なコードが含まれています。インターフェースはdwarfs/writer/
で定義されます。
dwarfs_rewrite
DwarFS イメージを再書き込みするコードが含まれています。インターフェースはdwarfs/utility/rewrite_filesystem.h
で定義されています。
internal
サブフォルダー内のヘッダーはビルド時にのみアクセスでき、インストールされません。 tool
サブフォルダーについても同様です。
リーダー API とエクストラクター API はかなり安定しているはずです。ライター API は変更される可能性があります。ただし、このプロジェクトがバージョン 1.0.0 に達するまでは API の安定性は保証されないことに注意してください。
Windows オペレーティング システムのサポートは現在実験段階です。過去 20 年間、もっぱら Unix の世界で働いてきた私の Windows 開発経験はかなり限られており、Windows コードには間違いなくバグや荒削りな部分があると予想しています。
Windows バージョンの DwarFS ファイルシステム ドライバーは素晴らしい WinFsp プロジェクトに依存しており、そのwinfsp-x64.dll
がdwarfs.exe
ドライバーによって検出可能である必要があります。
Linux で使用している場合でも Windows で使用している場合でも、さまざまなツールはほぼ同じように動作するはずです。ファイル システム イメージは Linux と Windows の間でコピーでき、一方の OS で作成されたイメージはもう一方の OS でも正常に動作します。
ただし、指摘する価値のあることがいくつかあります。
DwarFS は、Linux と同様に、Windows 上でもハードリンクとシンボリックリンクの両方をサポートします。ただし、ハードリンクとシンボリックリンクの作成には Windows の管理者権限が必要なようです。そのため、たとえば、ある種のリンクを含む DwarFS イメージを抽出したい場合、適切な権限がないとエラーが発生する可能性があります。
WinFsp の問題により、現在シンボリックリンクはマウントされたファイル システムの外部を指すことができません。さらに、WinFsp の別の問題により、ドライブ文字を含むシンボリックリンクが壊れたターゲット パスとともに表示されます。
Windows 上の DwarFS ドライバーは、その API を介してハードリンク数を正しく報告しますが、現在、これらの数は Windows ファイル システム層に正しく伝達されません。これはおそらく WinFsp の問題が原因と考えられます。
Windows に DwarFS イメージをマウントする場合、マウント ポイントが存在してはなりません。これは、マウント ポイントが実際に存在する必要がある Linux とは異なります。また、DwarFS イメージをドライブ文字としてマウントすることもできます。
dwarfs.exe image.dwarfs Z:
mkdwarfs
のフィルター ルールには、Windows と Linux のどちらで実行されているかに関係なく、常に Unix パス区切り文字が必要です。
vcpkg のおかげで、Windows でのビルドはそれほど複雑ではありません。以下をインストールする必要があります:
Visual Studio と MSVC C/C++ コンパイラ
Git
CMake
忍者
WinFsp
WinFsp
C:Program Files (x86)WinFsp
にインストールされることが想定されています。そうでない場合は、 cmake/win.bat
経由で CMake を実行するときにWINFSP_PATH
を設定する必要があります。
次に、 vcpkg
とdwarfs
クローンを作成する必要があります。
> cd %HOMEPATH%
> mkdir git
> cd git
> git clone https://github.com/Microsoft/vcpkg.git
> git clone https://github.com/mhx/dwarfs
次に、 vcpkg
をブートストラップします。
> .vcpkgbootstrap-vcpkg.bat
そして DwarFS を構築します。
> cd dwarfs
> mkdir build
> cd build
> ..cmakewin.bat
> ninja
それが完了すると、テストを実行できるようになります。マシンの CPU コアの数に応じてCTEST_PARALLEL_LEVEL
を設定します。
> set CTEST_PARALLEL_LEVEL=10
> ninja test
DwarFS ライブラリとツール ( mkdwarfs
、 dwarfsck
、 dwarfsextract
) が Homebrew から入手できるようになりました。
$ brew install dwarfs
$ brew test dwarfs
macOS バージョンの DwarFS ファイルシステム ドライバーは、素晴らしい macFUSE プロジェクトに依存しています。式が追加されるまでは、DwarFS FUSE ドライバーを手動で構築する必要があります。
macOS 上での構築は比較的簡単です。
自作をインストールする
Homebrew を使用して必要な依存関係をインストールします。
$ brew install cmake ninja macfuse brotli howard-hinnant-date double-conversion
fmt glog libarchive libevent flac openssl nlohmann-json pkg-config
range-v3 utf8cpp xxhash boost zstd
macFUSE を初めてインストールするときは、 「システム環境設定/プライバシーとセキュリティ」でソフトウェアを明示的に許可する必要があります。この後、再起動が必要になる可能性が高くなります。
リリース ページからリリース tarball をダウンロードして解凍します。
$ wget https://github.com/mhx/dwarfs/releases/download/v0.10.0/dwarfs-0.10.0.tar.xz
$ tar xf dwarfs-0.10.0.tar.xz
$ cmake --fresh -B dwarfs-build -S dwarfs-0.10.0 -GNinja -DWITH_TESTS=ON
$ cmake --build dwarfs-build
$ ctest --test-dir dwarfs-build -j
brew install
からmacfuse
省略し、上記の最初のcmake
コマンドの代わりに次のコマンドを使用できます。 $ cmake --fresh -B dwarfs-build -S dwarfs-0.10.0 -GNinja -DWITH_TESTS=ON -DWITH_FUSE_DRIVER=OFF
$ cmake --fresh -B dwarfs-build -S dwarfs-0.10.0 -GNinja -DWITH_TESTS=ON -DWITH_LIBDWARFS=OFF -DWITH_TOOLS=OFF
$ sudo cmake --install dwarfs-build
それでおしまい!
天体写真では、大量の生画像データが生成されることがあります。一晩の間に、数十ギガバイトのデータが溜まることも珍しくありません。ほとんどの天体写真専用カメラでは、このデータは FITS 画像の形式になります。これらは通常非圧縮であり、標準の圧縮アルゴリズムではあまり圧縮されません。また、特定の圧縮 FITS 形式はありますが、広くサポートされていません。
圧縮形式の 1 つ (単に「Rice」と呼ばれる) は、適切に圧縮され、非常に高速です。ただし、圧縮 FITS の実装にはいくつかの欠点があります。最も深刻な欠点は、カラー センサーや解像度が 16 ビット未満のセンサーほど圧縮が不十分であることです。
DwarFS は、 ricepp
(Rice++) 圧縮をサポートしています。これは、Rice 圧縮の基本的な考え方に基づいて構築されていますが、いくつかの機能拡張が行われています。カラー画像と低ビット深度の画像を大幅に圧縮し、圧縮中にヒューリスティックに依存する代わりに常に最適なソリューションを検索します。 。
ASI1600MM カメラで撮影した 129 枚の画像 (暗い、平坦、明るい) を使用した例を見てみましょう。各イメージは 32 MiB なので、合計 4 GiB のデータになります。これらを標準のfpack
ツールで圧縮すると、約 16.6 秒かかり、合計出力サイズは 2.2 GiB になります。
$ time fpack */*.fit */*/*.fit
user 14.992
system 1.592
total 16.616
$ find . -name '*.fz' -print0 | xargs -0 cat | wc -c
2369943360
ただし、これにより、すべてのアプリケーションが実際に読み取れるわけではない*.fz
ファイルが残ります。
DwarFS を使用すると、次のことが得られます。
$ mkdwarfs -i ASI1600 -o asi1600-20.dwarfs -S 20 --categorize
I 08:47:47.459077 scanning "ASI1600"
I 08:47:47.491492 assigning directory and link inodes...
I 08:47:47.491560 waiting for background scanners...
I 08:47:47.675241 scanning CPU time: 1.051s
I 08:47:47.675271 finalizing file inodes...
I 08:47:47.675330 saved 0 B / 3.941 GiB in 0/258 duplicate files
I 08:47:47.675360 assigning device inodes...
I 08:47:47.675371 assigning pipe/socket inodes...
I 08:47:47.675381 building metadata...
I 08:47:47.675393 building blocks...
I 08:47:47.675398 saving names and symlinks...
I 08:47:47.675514 updating name and link indices...
I 08:47:47.675796 waiting for segmenting/blockifying to finish...
I 08:47:50.274285 total ordering CPU time: 616.3us
I 08:47:50.274329 total segmenting CPU time: 1.132s
I 08:47:50.279476 saving chunks...
I 08:47:50.279622 saving directories...
I 08:47:50.279674 saving shared files table...
I 08:47:50.280745 saving names table... [1.047ms]
I 08:47:50.280768 saving symlinks table... [743ns]
I 08:47:50.282031 waiting for compression to finish...
I 08:47:50.823924 compressed 3.941 GiB to 1.201 GiB (ratio=0.304825)
I 08:47:50.824280 compression CPU time: 17.92s
I 08:47:50.824316 filesystem created without errors [3.366s]
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
waiting for block compression to finish
5 dirs, 0/0 soft/hard links, 258/258 files, 0 other
original size: 3.941 GiB, hashed: 315.4 KiB (18 files, 0 B/s)
scanned: 3.941 GiB (258 files, 117.1 GiB/s), categorizing: 0 B/s
saved by deduplication: 0 B (0 files), saved by segmenting: 0 B
filesystem: 3.941 GiB in 4037 blocks (4550 chunks, 516/516 fragments, 258 inodes)
compressed filesystem: 4037 blocks/1.201 GiB written
3.4 秒未満で、データはfpack
出力のほぼ半分のサイズである 1.2 GiB まで圧縮されます。
これは、ディスク容量を大幅に節約できるだけでなく、データを NAS に保存する場合にも役立ちます。以下は、1 Gb/秒のネットワーク接続を介してアクセスされた同じデータ セットの比較です。最初は非圧縮の生データを使用しています。
find /mnt/ASI1600 -name '*.fit' -print0 | xargs -0 -P4 -n1 cat | dd of=/dev/null status=progress
4229012160 bytes (4.2 GB, 3.9 GiB) copied, 36.0455 s, 117 MB/s
次に、同じ共有上の DwarFS イメージを使用します。
$ dwarfs /mnt/asi1600-20.dwarfs mnt
$ find mnt -name '*.fit' -print0 | xargs -0 -P4 -n1 cat | dd of=/dev/null status=progress
4229012160 bytes (4.2 GB, 3.9 GiB) copied, 14.3681 s, 294 MB/s
およそ 2.5 倍の速度になります。低速の外付けハードドライブでも同様の結果が発生する可能性が非常に高くなります。
現在、DwarFS にはファイル システム イメージに回復情報を追加する機能が組み込まれていません。ただし、アーカイブ目的の場合は、破損したイメージを修復できるように、そのような回復情報を用意しておくことをお勧めします。
幸いなことに、これは par2cmdline のようなものを使用することで比較的簡単です。
$ par2create -n1 asi1600-20.dwarfs
これにより、DwarFS がファイル システム イメージの問題を検出した場合にのみ必要となるため、イメージと一緒に (または別のストレージに) 配置できる 2 つの追加ファイルが作成されます。問題がある場合は実行できます
$ par2repair asi1600-20.dwarfs
これにより、イメージの 5% ( par2create
で使用されるデフォルト) 未満が破損していれば、イメージを回復できる可能性が高くなります。
拡張属性は現在サポートされていません。ソース ファイル システムに保存されている拡張属性は、現在、 mkdwarfs
使用して DwarFS イメージを構築するときに保存されません。
そうは言っても、マウントされた DwarFS イメージのルート i ノードは現在、Linux 上で 1 つまたは 2 つの拡張属性を公開しています。
$ attr -l mnt
Attribute "dwarfs.driver.pid" has a 4 byte value for mnt
Attribute "dwarfs.driver.perfmon" has a 4849 byte value for mnt
dwarfs.driver.pid
属性には、DwarFS FUSE ドライバーの PID が含まれるだけです。 dwarfs.driver.perfmon
属性には、パフォーマンス モニターの現在の結果が含まれています。
さらに、各通常ファイルは、基礎となる i ノードに関する情報を含む属性dwarfs.inodeinfo
公開します。
$ attr -l "05 Disappear.caf"
Attribute "dwarfs.inodeinfo" has a 448 byte value for 05 Disappear.caf
この属性には、基になる i ノードに関する情報を含む JSON オブジェクトが含まれます。
$ attr -qg dwarfs.inodeinfo "05 Disappear.caf"
{
"chunks": [
{
"block": 2,
"category": "pcmaudio/metadata",
"offset": 270976,
"size": 4096
},
{
"block": 414,
"category": "pcmaudio/waveform",
"offset": 37594368,
"size": 29514492
},
{
"block": 419,
"category": "pcmaudio/waveform",
"offset": 0,
"size": 29385468
}
],
"gid": 100,
"mode": 33188,
"modestring": "----rw-r--r--",
"uid": 1000
}
これは、たとえば、特定のファイルが複数のブロックにどのように分散されているか、またはファイルにどのカテゴリが割り当てられているかを確認する場合に便利です。
SquashFS、 xz
、 lrzip
、 zpaq
、およびwimlib
テストはすべて、64 GiB の RAM を搭載した 8 コア Intel(R) Xeon(R) E-2286M CPU @ 2.40GHz で実行されました。
Cromfs テストは、64 GiB の RAM を搭載した 6 コア Intel(R) Xeon(R) CPU D-1528 @ 1.90GHz 上の古いバージョンの DwarFS を使用して行われました。
EROFS テストは、64 GiB の RAM を搭載した Intel(R) Core(TM) i9-13900K 上の DwarFS v0.9.8 および EROFS v1.7.1 を使用して実行されました。
すべてのテスト中、システムはほとんどアイドル状態でした。
ソース ディレクトリには、284 の異なるリリースからの1139 の異なる Perl インストールが含まれており、1,927,501 のファイルと 330,733 のディレクトリに合計 47.65 GiB のデータが含まれていました。ソース ディレクトリは tar アーカイブから 970 EVO Plus 2TB NVME ドライブ上の XFS パーティションに新たに解凍されたため、その内容のほとんどがキャッシュされている可能性があります。
SquashFS には、DwarFS のデフォルト設定と同じ圧縮タイプと圧縮レベルを使用しています。
$ time mksquashfs install perl-install.squashfs -comp zstd -Xcompression-level 22
Parallel mksquashfs: Using 16 processors
Creating 4.0 filesystem on perl-install-zstd.squashfs, block size 131072.
[=========================================================/] 2107401/2107401 100%
Exportable Squashfs 4.0 filesystem, zstd compressed, data block size 131072
compressed data, compressed metadata, compressed fragments,
compressed xattrs, compressed ids
duplicates are removed
Filesystem size 4637597.63 Kbytes (4528.90 Mbytes)
9.29% of uncompressed filesystem size (49922299.04 Kbytes)
Inode table size 19100802 bytes (18653.13 Kbytes)
26.06% of uncompressed inode table size (73307702 bytes)
Directory table size 19128340 bytes (18680.02 Kbytes)
46.28% of uncompressed directory table size (41335540 bytes)
Number of duplicate files found 1780387
Number of inodes 2255794
Number of files 1925061
Number of fragments 28713
Number of symbolic links 0
Number of device nodes 0
Number of fifo nodes 0
Number of socket nodes 0
Number of directories 330733
Number of ids (unique uids + gids) 2
Number of uids 1
mhx (1000)
Number of gids 1
users (100)
real 32m54.713s
user 501m46.382s
sys 0m58.528s
DwarFS については、デフォルトのままにします。
$ time mkdwarfs -i install -o perl-install.dwarfs
I 11:33:33.310931 scanning install
I 11:33:39.026712 waiting for background scanners...
I 11:33:50.681305 assigning directory and link inodes...
I 11:33:50.888441 finding duplicate files...
I 11:34:01.120800 saved 28.2 GiB / 47.65 GiB in 1782826/1927501 duplicate files
I 11:34:01.122608 waiting for inode scanners...
I 11:34:12.839065 assigning device inodes...
I 11:34:12.875520 assigning pipe/socket inodes...
I 11:34:12.910431 building metadata...
I 11:34:12.910524 building blocks...
I 11:34:12.910594 saving names and links...
I 11:34:12.910691 bloom filter size: 32 KiB
I 11:34:12.910760 ordering 144675 inodes using nilsimsa similarity...
I 11:34:12.915555 nilsimsa: depth=20000 (1000), limit=255
I 11:34:13.052525 updating name and link indices...
I 11:34:13.276233 pre-sorted index (660176 name, 366179 path lookups) [360.6ms]
I 11:35:44.039375 144675 inodes ordered [91.13s]
I 11:35:44.041427 waiting for segmenting/blockifying to finish...
I 11:37:38.823902 bloom filter reject rate: 96.017% (TPR=0.244%, lookups=4740563665)
I 11:37:38.823963 segmentation matches: good=454708, bad=6819, total=464247
I 11:37:38.824005 segmentation collisions: L1=0.008%, L2=0.000% [2233254 hashes]
I 11:37:38.824038 saving chunks...
I 11:37:38.860939 saving directories...
I 11:37:41.318747 waiting for compression to finish...
I 11:38:56.046809 compressed 47.65 GiB to 430.9 MiB (ratio=0.00883101)
I 11:38:56.304922 filesystem created without errors [323s]
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
waiting for block compression to finish
330733 dirs, 0/2440 soft/hard links, 1927501/1927501 files, 0 other
original size: 47.65 GiB, dedupe: 28.2 GiB (1782826 files), segment: 15.19 GiB
filesystem: 4.261 GiB in 273 blocks (319178 chunks, 144675/144675 inodes)
compressed filesystem: 273 blocks/430.9 MiB written [depth: 20000]
█████████████████████████████████████████████████████████████████████████████▏100% |
real 5m23.030s
user 78m7.554s
sys 1m47.968s
したがって、この比較では、CPU 時間と実時間の両方の点で、 mkdwarfs
mksquashfs
より6 倍以上高速です。
$ ll perl-install.*fs
-rw-r--r-- 1 mhx users 447230618 Mar 3 20:28 perl-install.dwarfs
-rw-r--r-- 1 mhx users 4748902400 Mar 3 20:10 perl-install.squashfs
圧縮率の点では、 DwarFS ファイル システムは SquashFS ファイル システムよりも 10 分の 1 以上小さいです。 DwarFS を使用すると、コンテンツは元のサイズの 0.9% (!) 未満に圧縮されます。この圧縮率では、実際に使用されるディスク容量ではなく、個々のファイルに保存されているデータのみが考慮されます。 du
によると、元の XFS ファイル システムでは、ソース フォルダーは 52 GiB を使用するため、 DwarFS イメージは実際には元の領域の 0.8% しか使用しません。
zstd
の代わりにlzma
圧縮を使用した別の比較を次に示します。
$ time mksquashfs install perl-install-lzma.squashfs -comp lzma
real 13m42.825s
user 205m40.851s
sys 3m29.088s
$ time mkdwarfs -i install -o perl-install-lzma.dwarfs -l9
real 3m43.937s
user 49m45.295s
sys 1m44.550s
$ ll perl-install-lzma.*fs
-rw-r--r-- 1 mhx users 315482627 Mar 3 21:23 perl-install-lzma.dwarfs
-rw-r--r-- 1 mhx users 3838406656 Mar 3 20:50 perl-install-lzma.squashfs
実行が大幅に高速化され、結果として得られる画像が大幅に小さくなっていることがすぐにわかります。それでも、 mkdwarfs
は SquashFS イメージよりも約4 倍高速で、生成されるイメージのサイズは12 分の 1 です。 DwarFS イメージは、元のファイル サイズのわずか 0.6% です。
では、デフォルトでzstd
の代わりにlzma
使用してみてはいかがでしょうか?その理由は、 lzma
解凍がzstd
よりも約 1 桁遅いためです。圧縮ファイル システム上のデータにたまにしかアクセスしない場合は、これは大した問題ではないかもしれませんが、頻繁に使用する場合は、 zstd
方がパフォーマンスが向上します。
上記の比較は完全に公平ではありません。 mksquashfs
デフォルトで 128KiB のブロック サイズを使用しますが、 mkdwarfs
デフォルトで 16MiB ブロックを使用し、 -l9
を使用すると 64MiB ブロックも使用します。両方のファイル システムで同一のブロック サイズを使用すると、予想通り、違いはそれほど劇的ではなくなります。
$ time mksquashfs install perl-install-lzma-1M.squashfs -comp lzma -b 1M
real 15m43.319s
user 139m24.533s
sys 0m45.132s
$ time mkdwarfs -i install -o perl-install-lzma-1M.dwarfs -l9 -S20 -B3
real 4m25.973s
user 52m15.100s
sys 7m41.889s
$ ll perl-install*.*fs
-rw-r--r-- 1 mhx users 935953866 Mar 13 12:12 perl-install-lzma-1M.dwarfs
-rw-r--r-- 1 mhx users 3407474688 Mar 3 21:54 perl-install-lzma-1M.squashfs
これでも、DwarFS が最大 2 つの以前のファイル システム ブロックからファイル チャンクを参照できるようにする機能 ( -B3
) が使用されているため、完全に公平というわけではありません。
しかし重要なのは、SquashFS はより大きなブロック サイズや逆参照をサポートしていないため、これが SquashFS の最も優れた点であるということです。また、以下でわかるように、DwarFS がデフォルトで使用している大きなブロックが必ずしもパフォーマンスに悪影響を与えるわけではありません。
DwarFS には、異なる圧縮アルゴリズムを使用して既存のファイル システムを再圧縮するオプションもあります。これは、ファイル システムを完全に再構築する必要がなく、さまざまなアルゴリズムやオプションを比較的迅速に実験できるため便利です。たとえば、上記のファイル システムを可能な限り最適な圧縮 ( -l 9
) で再圧縮します。
$ time mkdwarfs --recompress -i perl-install.dwarfs -o perl-lzma-re.dwarfs -l9
I 20:28:03.246534 filesystem rewrittenwithout errors [148.3s]
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
filesystem: 4.261 GiB in 273 blocks (0 chunks, 0 inodes)
compressed filesystem: 273/273 blocks/372.7 MiB written
████████████████████████████████████████████████████████████████████▏100%
real 2m28.279s
user 37m8.825s
sys 0m43.256s