Усовершенствованная файловая система , доступная только для чтения, с дедупликацией Warp -speed.
Быстрая файловая система только для чтения с высокой степенью сжатия для Linux и Windows.
DwarFS — это файловая система, доступная только для чтения, в которой основное внимание уделяется достижению очень высокой степени сжатия, особенно для очень избыточных данных.
Вероятно, это звучит не очень интересно, потому что, если это избыточно, оно должно хорошо сжиматься. Однако я обнаружил, что другие сжатые файловые системы, доступные только для чтения, не очень хорошо справляются с использованием этой избыточности. См. здесь сравнение с другими сжатыми файловыми системами.
DwarFS также не идет на компромисс по скорости , и в моих случаях использования я обнаружил, что она находится на одном уровне или работает лучше, чем SquashFS. В моем основном случае использования сжатие DwarFS на порядок лучше, чем сжатие SquashFS , создание файловой системы происходит в 6 раз быстрее , доступ к файлам в DwarFS обычно быстрее и он использует меньше ресурсов ЦП.
Чтобы дать вам представление о том, на что способна DwarFS, вот краткое сравнение DwarFS и SquashFS на наборе видеофайлов общим размером 39 ГиБ. Особенность в том, что каждый уникальный видеофайл имеет два родственных файла с разными наборами аудиопотоков (это реальный вариант использования). Таким образом, как в видео, так и в аудиоданных существует избыточность, но поскольку потоки чередуются, а идентичные блоки обычно находятся очень далеко друг от друга, использовать эту избыточность для сжатия сложно. SquashFS по сути вообще не может сжать исходные данные, тогда как DwarFS способна уменьшить размер почти в 3 раза, что близко к теоретическому максимуму:
$ 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 МБ/с:
$ 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 ГиБ/с :
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 являются:
Кластеризация файлов по сходству с использованием хеш-функции сходства. Это упрощает использование избыточности за пределами файловых границ.
Анализ сегментации по блокам файловой системы с целью уменьшения размера несжатой файловой системы. Это экономит память при использовании сжатой файловой системы и, таким образом, потенциально обеспечивает более высокую частоту попаданий в кэш, поскольку в кэше может храниться больше данных.
Структура категоризации для категоризации файлов или даже фрагментов файлов и последующей обработки отдельных категорий по-разному. Например, это позволяет не тратить время на попытки сжать несжимаемые файлы или сжать аудиоданные PCM с помощью сжатия FLAC.
Очень многопоточная реализация. И инструмент создания файловой системы, и драйвер FUSE могут эффективно использовать множество ядер вашей системы.
Я начал работать над DwarFS в 2013 году, и моим основным вариантом использования и основной мотивацией было то, что у меня было несколько сотен различных версий Perl, которые занимали около 30 гигабайт дискового пространства, и я не хотел тратить более 10% моего жесткого диска. езжу, оставляя их под рукой на случай, если они мне понадобятся.
До этого я использовал Cromfs для сжатия их до приемлемого размера. Однако меня все больше и больше раздражало время, необходимое для создания образа файловой системы, и, что еще хуже, чаще всего примерно через час или около того происходил сбой.
Я, очевидно, также изучал SquashFS, но так и не приблизился к степени сжатия Cromfs.
Одного этого было бы недостаточно, чтобы заставить меня написать DwarFS, но примерно в то же время я был довольно одержим недавними разработками и особенностями новых стандартов C++ и очень хотел заняться хобби-проектом C++, над которым можно было бы работать. Кроме того, я уже давно хотел сделать что-нибудь с FUSE. И последнее, но не менее важное: я некоторое время размышлял о проблеме сжатых файловых систем, и у меня возникли некоторые идеи, которые я определенно хотел реализовать.
Большая часть кода была написана в 2013 году, затем я время от времени делал пару чисток, исправлений ошибок и рефакторингов, но мне так и не удалось довести его до состояния, когда я был бы счастлив выпустить его. Его было слишком неудобно создавать, используя (довольно потрясающую) библиотеку Folly от Facebook, и у него не было никакой документации.
Когда в этом году снова раскопали проект, все выглядело не так мрачно, как раньше. Folly теперь собирается с помощью CMake, поэтому я просто включил его как подмодуль. Большинство других зависимостей можно удовлетворить с помощью пакетов, которые должны быть широко доступны. И я также написал несколько элементарных документов.
DwarFS обычно должна работать нормально с минимальными изменениями из коробки. Если это не так, пожалуйста, сообщите о проблеме. Я настроил задания CI, используя образы Docker для Ubuntu (22.04 и 24.04), Fedora Rawhide и Arch, которые могут помочь в определении актуального набора зависимостей. Обратите внимание, что сборка из архива выпуска требует меньше зависимостей, чем сборка из репозитория git, в частности, инструмент ronn
, а также Python и модуль Python mistletoe
не требуются при сборке из архива выпуска.
Есть некоторые вещи, о которых следует знать:
Существует тенденция попытаться разделить библиотеки folly и fbthrift, которые включены в качестве подмодулей и создаются вместе с DwarFS. Хотя я согласен с этим мнением, к сожалению, это плохая идея. Помимо того факта, что folly не претендует на стабильность ABI (т. е. вы не можете просто динамически связать двоичный файл, созданный на основе одной версии folly, с другой версией), невозможно даже безопасно скомпоновать библиотеку folly, созданную с помощью другой компиляции. параметры. Даже незначительные различия, такие как стандартная версия C++, могут вызвать ошибки во время выполнения. Подробности смотрите в этом выпуске. В настоящее время невозможно даже использовать внешние версии folly/fbthrift, поскольку DwarFS собирает минимальные подмножества обеих библиотек; они включены в библиотеку dwarfs_common
и используются исключительно для внутреннего использования, т.е. ни один из заголовков folly или fbthrift не требуется для сборки с использованием библиотек DwarFS.
Аналогичные проблемы могут возникнуть при использовании установленной в системе версии GoogleTest. Сам GoogleTest рекомендует загружать его как часть сборки. Однако вы можете использовать версию, установленную в системе, передав -DPREFER_SYSTEM_GTEST=ON
в вызов cmake
. Используйте на свой страх и риск.
Для других встроенных библиотек (а именно fmt
, parallel-hashmap
, range-v3
) используется версия, установленная в системе, если она соответствует минимально необходимой версии. В противном случае предпочтительная версия будет выбрана во время сборки.
В каждом выпуске есть предварительно созданные статически связанные двоичные файлы для Linux-x86_64
, Linux-aarch64
и Windows-AMD64
, доступные для загрузки. Они должны работать без каких-либо зависимостей и могут быть полезны, особенно в старых дистрибутивах, где вы не можете легко собрать инструменты из исходного кода.
Помимо бинарных архивов, для каждой архитектуры доступен универсальный двоичный файл . Эти универсальные двоичные файлы содержат все инструменты ( mkdwarfs
, dwarfsck
, dwarfsextract
и драйвер dwarfs
FUSE) в одном исполняемом файле. Эти исполняемые файлы сжимаются с помощью 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
Обратите внимание, что универсальный двоичный файл Windows, как и двоичный файл dwarfs.exe
, зависит от файла winfsp-x64.dll
из проекта WinFsp. Однако в универсальном двоичном файле 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
уровень оптимизации будет установлен на -O2
вместо значения по умолчанию CMake -O3
для выпускных сборок. По крайней мере, в версиях до gcc-10
сборка -O3
работает на 70 % медленнее, чем сборка с -O2
.
Сначала распакуйте архив релиза:
$ 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
, передайте -DUSE_JEMALLOC=0
в командной строке cmake
.
Также можно самостоятельно собрать/установить библиотеки, инструменты и драйвер FUSE DwarFS. Это особенно интересно при упаковке 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
не являются обязательными, но помогают ускорить компиляцию.
В зависимости от вашего дистрибутива вам потребуется собрать и установить статические версии некоторых библиотек, например libarchive
и libmagic
для Ubuntu:
$ 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
.
Использование библиотек DwarFS должно быть довольно простым, если вы используете CMake для сборки своего проекта. Для быстрого начала взгляните на пример кода, который использует библиотеки для печати информации об образе DwarFS (например, dwarfsck
) или ее извлечения (например, dwarfsextract
).
Есть пять отдельных библиотек:
dwarfs_common
содержит общий код, необходимый для всех остальных библиотек. Интерфейсы определены в dwarfs/
.
dwarfs_reader
содержит весь код, необходимый для чтения данных из образа DwarFS. Интерфейсы определены в dwarfs/reader/
.
dwarfs_extractor
содержит код, необходимый для извлечения образа DwarFS с помощью libarchive
. Интерфейсы определены в 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.
Поддержка операционной системы Windows в настоящее время находится на экспериментальной стадии. Поскольку последние два десятилетия я работал практически исключительно в мире Unix, мой опыт разработки для Windows довольно ограничен, и я ожидаю, что в коде Windows обязательно будут ошибки и неровности.
Версия драйвера файловой системы DwarFS для Windows основана на замечательном проекте WinFsp, и его winfsp-x64.dll
должен быть доступен для обнаружения драйвером dwarfs.exe
.
Различные инструменты должны вести себя примерно одинаково, используете ли вы их в Linux или Windows. Образы файловой системы можно копировать между Linux и Windows, а образы, созданные в одной ОС, должны нормально работать в другой.
Однако есть несколько вещей, на которые стоит обратить внимание:
DwarFS поддерживает как жесткие, так и символические ссылки в Windows, так же, как и в Linux. Однако для создания жестких и символических ссылок требуются права администратора в Windows, поэтому, если вы хотите, например, извлечь образ DwarFS, содержащий какие-либо ссылки, вы можете столкнуться с ошибками, если у вас нет необходимых привилегий.
Из-за проблемы в WinFsp символические ссылки в настоящее время не могут указывать за пределы смонтированной файловой системы. Кроме того, из-за другой проблемы в WinFsp символические ссылки с буквой диска будут отображаться с искаженным целевым путем.
Драйвер DwarFS в Windows правильно сообщает о количестве жестких ссылок через свой API, но в настоящее время эти значения не передаются правильно на уровень файловой системы Windows. Предположительно это связано с проблемой в WinFsp.
При монтировании образа DwarFS в Windows точка монтирования не должна существовать. Это отличается от Linux, где точка монтирования действительно должна существовать. Кроме того, можно смонтировать образ DwarFS как букву диска, например
dwarfs.exe image.dwarfs Z:
Правила фильтрации для mkdwarfs
всегда требуют разделителей путей Unix, независимо от того, работает ли он в Windows или Linux.
Сборка под Windows не так уж и сложна благодаря vcpkg. Вам потребуется установить:
Visual Studio и компилятор MSVC C/C++.
Гит
CMake
Ниндзя
WinFsp
Ожидается, что WinFsp
будет установлен в C:Program Files (x86)WinFsp
; если это не так, вам нужно будет установить WINFSP_PATH
при запуске CMake через cmake/win.bat
.
Теперь вам нужно клонировать 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
Как только это будет сделано, вы сможете запустить тесты. Установите CTEST_PARALLEL_LEVEL
в соответствии с количеством ядер ЦП на вашем компьютере.
> set CTEST_PARALLEL_LEVEL=10
> ninja test
Библиотеки и инструменты DwarFS ( mkdwarfs
, dwarfsck
, dwarfsextract
) теперь доступны на Homebrew:
$ brew install dwarfs
$ brew test dwarfs
Версия драйвера файловой системы DwarFS для macOS основана на замечательном проекте 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 вам необходимо явно разрешить использование программного обеспечения в разделе «Системные настройки» / «Конфиденциальность и безопасность» . Вполне вероятно, что после этого вам придется перезагрузиться.
Загрузите архив релизов со страницы релизов и распакуйте его:
$ 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
macfuse
из brew install
и использовать следующую команду вместо первой команды 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, они не получили широкой поддержки.
Один из форматов сжатия (называемый просто «Рис») сжимает достаточно хорошо и очень быстро. Однако его реализация для сжатых FITS имеет несколько недостатков. Самый серьезный недостаток заключается в том, что сжатие не так хорошо, как могло бы быть для датчиков цвета и датчиков с разрешением менее 16 бит.
DwarFS поддерживает сжатие ricepp
(Rice++), которое основано на базовой идее сжатия Rice, но имеет несколько улучшений: оно значительно лучше сжимает цветные изображения и изображения с низкой битовой глубиной и всегда ищет оптимальное решение во время сжатия, а не полагается на эвристику. .
Давайте рассмотрим пример, использующий 129 изображений (темных, плоских и светлых), снятых камерой ASI1600MM. Каждое изображение занимает 32 МБ, то есть общий объем данных составляет 4 ГБ. Сжатие их с помощью стандартного инструмента fpack
занимает около 16,6 секунды и дает общий размер вывода 2,2 ГиБ:
$ 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 секунды он сжимает данные до 1,2 ГиБ, что почти вдвое меньше размера выходных данных fpack
.
Помимо экономии места на диске, это также может быть полезно, если ваши данные хранятся на NAS. Вот сравнение того же набора данных, доступ к которым осуществляется через сетевое соединение со скоростью 1 Гбит/с, сначала с использованием несжатых необработанных данных:
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 обнаружит проблему с образом файловой системы. Если есть проблема, вы можете запустить
$ par2repair asi1600-20.dwarfs
который, скорее всего, сможет восстановить образ, если менее 5% (это значение по умолчанию, используемое par2create
) образа повреждено.
Расширенные атрибуты в настоящее время не поддерживаются. Любые расширенные атрибуты, хранящиеся в исходной файловой системе, в настоящее время не сохраняются при создании образа DwarFS с использованием mkdwarfs
.
При этом корневой индекс смонтированного образа DwarFS в настоящее время предоставляет один или два расширенных атрибута в Linux:
$ 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
просто содержит PID драйвера DwarFS FUSE. Атрибут dwarfs.driver.perfmon
содержит текущие результаты монитора производительности.
Более того, каждый обычный файл предоставляет атрибут dwarfs.inodeinfo
с информацией о базовом индексном дескрипторе:
$ attr -l "05 Disappear.caf"
Attribute "dwarfs.inodeinfo" has a 448 byte value for 05 Disappear.caf
Атрибут содержит объект 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
проводились на 8-ядерном процессоре Intel(R) Xeon(R) E-2286M с тактовой частотой 2,40 ГГц и 64 ГиБ оперативной памяти.
Тесты Cromfs проводились с использованием более старой версии DwarFS на 6-ядерном процессоре Intel(R) Xeon(R) D-1528 с частотой 1,90 ГГц и 64 ГиБ оперативной памяти.
Тесты EROFS проводились с использованием DwarFS v0.9.8 и EROFS v1.7.1 на процессоре Intel(R) Core(TM) i9-13900K с 64 ГиБ оперативной памяти.
Во время всех испытаний системы в основном простаивали.
Исходный каталог содержал 1139 различных установок Perl из 284 различных выпусков, общий объем данных 47,65 ГиБ в 1 927 501 файле и 330 733 каталогах. Исходный каталог был только что распакован из tar-архива в раздел XFS на NVME-накопителе 970 EVO Plus емкостью 2 ТБ, поэтому большая часть его содержимого, вероятно, была кэширована.
Я использую тот же тип и уровень сжатия для 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
Таким образом, в этом сравнении mkdwarfs
более чем в 6 раз быстрее, чем mksquashfs
, как с точки зрения времени процессора, так и времени настенных часов.
$ 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 более чем в 10 раз меньше файловой системы SquashFS . С помощью DwarFS контент сжимается до менее чем 0,9% (!) от исходного размера . Этот коэффициент сжатия учитывает только данные, хранящиеся в отдельных файлах, а не фактическое используемое дисковое пространство. В исходной файловой системе XFS, согласно du
, исходная папка занимает 52 ГиБ, поэтому образ DwarFS фактически использует только 0,8% исходного пространства .
Вот еще одно сравнение с использованием сжатия lzma
вместо zstd
:
$ 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
примерно в 4 раза быстрее и создает изображение в 12 раз меньше, чем изображение SquashFS. Размер образа DwarFS составляет всего 0,6% от исходного размера файла.
Итак, почему бы по умолчанию не использовать lzma
вместо zstd
? Причина в том, что lzma
распаковывает примерно на порядок медленнее, чем zstd
. Если вы получаете доступ к данным в вашей сжатой файловой системе лишь время от времени, это может не иметь большого значения, но если вы используете его широко, zstd
приведет к повышению производительности.
Приведенные выше сравнения не совсем справедливы. mksquashfs
по умолчанию использует размер блока 128 КБ, тогда как mkdwarfs
по умолчанию использует блоки размером 16 МБ или даже блоки 64 МБ с -l9
. При использовании одинаковых размеров блоков для обеих файловых систем разница, как и следовало ожидать, становится гораздо менее существенной:
$ 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
Даже это не совсем справедливо, поскольку здесь используется функция ( -B3
), которая позволяет DwarFS ссылаться на фрагменты файлов из двух предыдущих блоков файловой системы.
Но дело в том, что именно здесь 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