Le système de fichiers avancé en lecture seule à vitesse de distorsion élevée .
Un système de fichiers rapide en lecture seule à haute compression pour Linux et Windows.
DwarFS est un système de fichiers en lecture seule qui vise à atteindre des taux de compression très élevés, en particulier pour les données très redondantes.
Cela ne semble probablement pas très excitant, car s'il est redondant, il devrait bien se compresser. Cependant, j'ai constaté que d'autres systèmes de fichiers compressés en lecture seule ne font pas un très bon travail pour utiliser cette redondance. Voir ici pour une comparaison avec d'autres systèmes de fichiers compressés.
DwarFS ne fait pas non plus de compromis sur la vitesse et pour mes cas d'utilisation, je l'ai trouvé comparable ou plus performant que SquashFS. Pour mon cas d'utilisation principal, la compression DwarFS est d'un ordre de grandeur meilleure que la compression SquashFS , elle est 6 fois plus rapide pour construire le système de fichiers , elle est généralement plus rapide pour accéder aux fichiers sur DwarFS et elle utilise moins de ressources CPU.
Pour vous donner une idée de ce dont DwarFS est capable, voici une comparaison rapide de DwarFS et SquashFS sur un ensemble de fichiers vidéo d'une taille totale de 39 GiB. Le problème est que chaque fichier vidéo unique contient deux fichiers frères avec un ensemble différent de flux audio (il s'agit d'un cas d'utilisation réel). Il existe donc une redondance dans les données vidéo et audio, mais comme les flux sont entrelacés et que les blocs identiques sont généralement très éloignés les uns des autres, il est difficile d'utiliser cette redondance pour la compression. SquashFS ne parvient essentiellement pas à compresser les données sources, alors que DwarFS est capable de réduire la taille de près d'un facteur 3, ce qui est proche du maximum théorique :
$ 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
De plus, lors du montage de l'image SquashFS et de l'exécution d'un test de débit en lecture aléatoire à l'aide de fio-3.34, squashfuse
et squashfuse_ll
atteignent un maximum d'environ 230 Mio/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
En comparaison, DwarFS parvient à maintenir des taux de lecture aléatoire de 20 Gio/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
Les caractéristiques distinctives de DwarFS sont :
Regroupement de fichiers par similarité à l'aide d'une fonction de hachage de similarité. Cela facilite l'exploitation de la redondance au-delà des limites des fichiers.
Analyse de segmentation entre les blocs du système de fichiers afin de réduire la taille du système de fichiers non compressé. Cela permet d'économiser de la mémoire lors de l'utilisation du système de fichiers compressé et permet ainsi potentiellement des taux de réussite du cache plus élevés, car davantage de données peuvent être conservées dans le cache.
Cadre de catégorisation pour catégoriser des fichiers ou même des fragments de fichiers, puis traiter différemment les catégories individuelles. Par exemple, cela vous permet de ne pas perdre de temps à essayer de compresser des fichiers incompressibles ou de compresser des données audio PCM grâce à la compression FLAC.
Implémentation hautement multithread. L'outil de création de système de fichiers ainsi que le pilote FUSE sont capables de faire bon usage des nombreux cœurs de votre système.
J'ai commencé à travailler sur DwarFS en 2013 et mon principal cas d'utilisation et ma principale motivation était que j'avais plusieurs centaines de versions différentes de Perl qui occupaient environ 30 Go d'espace disque, et je n'étais pas disposé à dépenser plus de 10 % de mon temps dur. conduire en les gardant à portée de main lorsque j'en avais besoin.
Jusque-là, j'utilisais Cromfs pour les réduire à une taille gérable. Cependant, j'étais de plus en plus ennuyé par le temps qu'il fallait pour créer l'image du système de fichiers et, pour aggraver les choses, le plus souvent, elle plantait après environ une heure.
J'avais évidemment aussi étudié SquashFS, mais je ne me suis jamais rapproché des taux de compression de Cromfs.
Cela seul n'aurait pas suffi à me pousser à écrire DwarFS, mais à peu près au même moment, j'étais assez obsédé par les développements récents et les fonctionnalités des nouvelles normes C++ et je voulais vraiment travailler sur un projet de loisir C++. De plus, je voulais faire quelque chose avec FUSE depuis un certain temps. Enfin, je réfléchissais depuis un moment au problème des systèmes de fichiers compressés et j'avais quelques idées que je voulais absolument essayer.
La majorité du code a été écrite en 2013, puis j'ai effectué quelques nettoyages, corrections de bugs et refactorisations de temps en temps, mais je ne l'ai jamais vraiment amené à un état où je me sentirais heureux de le publier. C'était trop difficile à construire avec sa dépendance à la bibliothèque de folie (assez géniale) de Facebook et il n'avait aucune documentation.
En reprenant le projet cette année encore, les choses ne semblaient plus aussi sombres qu'avant. Folly est maintenant construit avec CMake et je l'ai donc simplement intégré en tant que sous-module. La plupart des autres dépendances peuvent être satisfaites à partir de packages qui devraient être largement disponibles. Et j'ai également écrit quelques documents rudimentaires.
DwarFS devrait généralement se construire correctement avec des modifications minimes dès la sortie de la boîte. Si ce n'est pas le cas, veuillez signaler un problème. J'ai configuré des tâches CI à l'aide d'images Docker pour Ubuntu (22.04 et 24.04), Fedora Rawhide et Arch qui peuvent aider à déterminer un ensemble de dépendances à jour. Notez que la construction à partir de l'archive tar de la version nécessite moins de dépendances que la construction à partir du référentiel git, notamment l'outil ronn
ainsi que Python et le module Python mistletoe
ne sont pas requis lors de la construction à partir de l'archive tar de la version.
Il y a certaines choses à prendre en compte :
Il y a une tendance à essayer de dégrouper les bibliothèques Folly et Fbthrift qui sont incluses en tant que sous-modules et construites avec DwarFS. Même si je suis d'accord avec ce sentiment, c'est malheureusement une mauvaise idée. Outre le fait que Folly ne fait aucune déclaration sur la stabilité de l'ABI (c'est-à-dire que vous ne pouvez pas simplement lier dynamiquement un binaire construit avec une version de Folly à une autre version), il n'est même pas possible de créer un lien en toute sécurité avec une bibliothèque Folly construite avec une compilation différente. choix. Même des différences subtiles, telles que la version standard C++, peuvent provoquer des erreurs d'exécution. Voir ce problème pour plus de détails. Actuellement, il n'est même pas possible d'utiliser des versions externes de folly/fbthrift car DwarFS construit des sous-ensembles minimaux des deux bibliothèques ; ceux-ci sont regroupés dans la bibliothèque dwarfs_common
et sont strictement utilisés en interne, c'est-à-dire qu'aucun des en-têtes folie ou fbthrift n'est requis pour être construit avec les bibliothèques de DwarFS.
Des problèmes similaires peuvent survenir lors de l’utilisation d’une version de GoogleTest installée sur le système. GoogleTest lui-même recommande qu'il soit téléchargé dans le cadre de la construction. Cependant, vous pouvez utiliser la version installée du système en passant -DPREFER_SYSTEM_GTEST=ON
à l'appel cmake
. Utilisez à vos propres risques.
Pour les autres bibliothèques groupées (à savoir fmt
, parallel-hashmap
, range-v3
), la version installée sur le système est utilisée tant qu'elle correspond à la version minimale requise. Sinon, la version préférée est récupérée lors de la construction.
Chaque version contient des binaires prédéfinis et liés statiquement pour Linux-x86_64
, Linux-aarch64
et Windows-AMD64
disponibles en téléchargement. Ceux-ci devraient fonctionner sans aucune dépendance et peuvent être utiles en particulier sur les anciennes distributions où vous ne pouvez pas facilement créer les outils à partir des sources.
En plus des archives binaires, il existe un binaire universel disponible pour chaque architecture. Ces binaires universels contiennent tous les outils ( mkdwarfs
, dwarfsck
, dwarfsextract
et le pilote dwarfs
FUSE) dans un seul exécutable. Ces exécutables sont compressés à l'aide d'upx, ils sont donc beaucoup plus petits que les outils individuels combinés. Cependant, cela signifie également que les binaires doivent être décompressés à chaque exécution, ce qui peut entraîner une surcharge importante. Si cela pose un problème, vous pouvez soit vous en tenir aux binaires individuels "classiques", soit décompresser le binaire universel, par exemple :
upx -d dwarfs-universal-0.7.0-Linux-aarch64
Les binaires universels peuvent être exécutés via des liens symboliques nommés d'après l'outil approprié. par exemple :
$ ln -s dwarfs-universal-0.7.0-Linux-aarch64 mkdwarfs
$ ./mkdwarfs --help
Cela fonctionne également sous Windows si le système de fichiers prend en charge les liens symboliques :
> mklink mkdwarfs.exe dwarfs-universal-0.7.0-Windows-AMD64.exe
> .mkdwarfs.exe --help
Alternativement, vous pouvez sélectionner l'outil en passant --tool=<name>
comme premier argument sur la ligne de commande :
> .dwarfs-universal-0.7.0-Windows-AMD64.exe --tool=mkdwarfs --help
Notez que tout comme le binaire Windows dwarfs.exe
, le binaire Windows universel dépend du winfsp-x64.dll
du projet WinFsp. Cependant, pour le binaire universel, la DLL est chargée paresseusement, vous pouvez donc toujours utiliser tous les autres outils sans la DLL. Consultez la section Assistance Windows pour plus de détails.
DwarFS utilise CMake comme outil de construction.
Il utilise à la fois Boost et Folly, bien que ce dernier soit inclus en tant que sous-module car très peu de distributions proposent réellement des packages pour celui-ci. Folly lui-même a un certain nombre de dépendances, veuillez donc consulter ici pour une liste à jour.
Il utilise également Facebook Thrift, en particulier la bibliothèque frozen
, pour stocker les métadonnées dans un format très économe en espace, mappable en mémoire et bien défini. Il est également inclus en tant que sous-module, et nous construisons uniquement le compilateur et une bibliothèque très réduite qui en contient juste assez pour que DwarFS fonctionne.
En dehors de cela, DwarFS ne dépend en réalité que de FUSE3 et d'un ensemble de bibliothèques de compression dont dépend déjà Folly (à savoir lz4, zstd et liblzma).
La dépendance à googletest sera automatiquement résolue si vous construisez avec des tests.
Un bon point de départ pour les systèmes basés sur apt est probablement :
$ 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
Notez que lors de la construction avec gcc
, le niveau d'optimisation sera défini sur -O2
au lieu de la valeur par défaut de CMake de -O3
pour les versions publiées. Au moins avec les versions jusqu'à gcc-10
, la build -O3
est jusqu'à 70 % plus lente qu'une build avec -O2
.
Tout d’abord, décompressez l’archive de la version :
$ tar xvf dwarfs-x.y.z.tar.xz
$ cd dwarfs-x.y.z
Alternativement, vous pouvez également cloner le référentiel git, mais sachez que cela a plus de dépendances et que la construction prendra probablement plus de temps car l'archive de version est livrée avec la plupart des fichiers générés automatiquement qui devront être générés lors de la construction à partir du référentiel :
$ git clone --recurse-submodules https://github.com/mhx/dwarfs
$ cd dwarfs
Une fois toutes les dépendances installées, vous pouvez construire DwarFS en utilisant :
$ mkdir build
$ cd build
$ cmake .. -GNinja -DWITH_TESTS=ON
$ ninja
Vous pouvez ensuite lancer des tests avec :
$ ctest -j
Tous les binaires utilisent jemalloc comme allocateur de mémoire par défaut, car il utilise généralement beaucoup moins de mémoire système que les allocateurs glibc
ou tcmalloc
. Pour désactiver l'utilisation de jemalloc
, transmettez -DUSE_JEMALLOC=0
sur la ligne de commande cmake
.
Il est également possible de créer/installer indépendamment les bibliothèques, les outils et le pilote FUSE de DwarFS. Ceci est particulièrement intéressant lors du packaging de DwarFS. Notez que les outils et le pilote FUSE nécessitent que les bibliothèques soient construites ou déjà installées. Pour construire uniquement les bibliothèques, utilisez :
$ cmake .. -GNinja -DWITH_TESTS=ON -DWITH_LIBDWARFS=ON -DWITH_TOOLS=OFF -DWITH_FUSE_DRIVER=OFF
Une fois les bibliothèques testées et installées, vous pouvez créer les outils (c'est-à-dire mkdwarfs
, dwarfsck
, dwarfsextract
) en utilisant :
$ cmake .. -GNinja -DWITH_TESTS=ON -DWITH_LIBDWARFS=OFF -DWITH_TOOLS=ON -DWITH_FUSE_DRIVER=OFF
Pour construire le pilote FUSE, utilisez :
$ cmake .. -GNinja -DWITH_TESTS=ON -DWITH_LIBDWARFS=OFF -DWITH_TOOLS=OFF -DWITH_FUSE_DRIVER=ON
L'installation est aussi simple que :
$ sudo ninja install
Bien que vous n'ayez pas besoin d'installer les outils pour jouer avec eux.
Tenter de créer des binaires liés statiquement est fortement déconseillé et n'est pas officiellement pris en charge. Cela étant dit, voici comment configurer un environnement dans lequel vous pourrez peut-être créer des binaires statiques.
Cela a été testé avec ubuntu-22.04-live-server-amd64.iso
. Tout d’abord, installez tous les packages répertoriés comme dépendances ci-dessus. Installez également :
$ apt install ccache ninja libacl1-dev
ccache
et ninja
sont facultatifs, mais facilitent une compilation rapide.
En fonction de votre distribution, vous devrez créer et installer des versions statiques de certaines bibliothèques, par exemple libarchive
et libmagic
pour 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
C'est ça! Vous pouvez maintenant essayer de créer des binaires statiques pour 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
Veuillez consulter les pages de manuel de mkdwarfs, dwarfs, dwarfsck et dwarfsextract. Vous pouvez également accéder aux pages de manuel en utilisant l'option --man
pour chaque binaire, par exemple :
$ mkdwarfs --man
La page de manuel de Dwarfs montre également un exemple de configuration de DwarFS avec overlayfs afin de créer un montage de système de fichiers inscriptible au-dessus d'une image DwarFS en lecture seule.
Une description du format du système de fichiers DwarFS peut être trouvée dans dwarfs-format.
Un aperçu de haut niveau du fonctionnement interne de mkdwarfs
est présenté dans ce diagramme de séquence.
L'utilisation des bibliothèques DwarFS devrait être assez simple si vous utilisez CMake pour créer votre projet. Pour un démarrage rapide, jetez un œil à l'exemple de code qui utilise les bibliothèques pour imprimer des informations sur une image DwarFS (comme dwarfsck
) ou l'extraire (comme dwarfsextract
).
Il existe cinq bibliothèques individuelles :
dwarfs_common
contient le code commun requis par toutes les autres bibliothèques. Les interfaces sont définies dans dwarfs/
.
dwarfs_reader
contient tout le code requis pour lire les données d'une image DwarFS. Les interfaces sont définies dans dwarfs/reader/
.
dwarfs_extractor
contient le ccode requis pour extraire une image DwarFS à l'aide de libarchive
. Les interfaces sont définies dans dwarfs/utility/filesystem_extractor.h
.
dwarfs_writer
contient le code requis pour créer des images DwarFS. Les interfaces sont définies dans dwarfs/writer/
.
dwarfs_rewrite
contient le code pour réécrire les images DwarFS. Les interfaces sont définies dans dwarfs/utility/rewrite_filesystem.h
.
Les en-têtes des sous-dossiers internal
ne sont accessibles qu'au moment de la construction et ne seront pas installés. Il en va de même pour le sous-dossier tool
.
Les API du lecteur et de l’extracteur doivent être assez stables. Les API du rédacteur vont probablement changer. Notez cependant qu'il n'y a aucune garantie sur la stabilité de l'API avant que ce projet n'atteigne la version 1.0.0.
La prise en charge du système d'exploitation Windows est actuellement expérimentale. Ayant travaillé presque exclusivement dans un monde Unix au cours des deux dernières décennies, mon expérience du développement Windows est plutôt limitée et je m'attendrais à ce qu'il y ait certainement des bugs et des aspérités dans le code Windows.
La version Windows du pilote du système de fichiers DwarFS repose sur le génial projet WinFsp et son winfsp-x64.dll
doit être détectable par le pilote dwarfs.exe
.
Les différents outils devraient se comporter à peu près de la même manière, que vous les utilisiez sous Linux ou Windows. Les images du système de fichiers peuvent être copiées entre Linux et Windows et les images créées sur un système d'exploitation devraient fonctionner correctement sur l'autre.
Il y a cependant quelques points à souligner :
DwarFS prend en charge à la fois les liens physiques et les liens symboliques sous Windows, tout comme sous Linux. Cependant, la création de liens physiques et de liens symboliques semble nécessiter des privilèges d'administrateur sous Windows. Par conséquent, si vous souhaitez, par exemple, extraire une image DwarFS contenant des liens, vous risquez de rencontrer des erreurs si vous ne disposez pas des privilèges appropriés.
En raison d'un problème dans WinFsp, les liens symboliques ne peuvent actuellement pas pointer en dehors du système de fichiers monté. De plus, en raison d'un autre problème dans WinFsp, les liens symboliques avec une lettre de lecteur apparaîtront avec un chemin cible mutilé.
Le pilote DwarFS sous Windows signale correctement le nombre de liens physiques via son API, mais actuellement ces comptes ne sont pas correctement propagés à la couche du système de fichiers Windows. Cela est probablement dû à un problème dans WinFsp.
Lors du montage d'une image DwarFS sous Windows, le point de montage ne doit pas exister. Ceci est différent de Linux, où le point de montage doit réellement exister. Il est également possible de monter une image DwarFS en tant que lettre de lecteur, par exemple
dwarfs.exe image.dwarfs Z :
Les règles de filtrage pour mkdwarfs
nécessitent toujours des séparateurs de chemin Unix, qu'il s'exécute sous Windows ou Linux.
Construire sous Windows n’est pas trop compliqué grâce à vcpkg. Vous devrez installer :
Visual Studio et le compilateur MSVC C/C++
Git
CMake
Ninja
WinFsp
WinFsp
devrait être installé dans C:Program Files (x86)WinFsp
; si ce n'est pas le cas, vous devrez définir WINFSP_PATH
lors de l'exécution de CMake via cmake/win.bat
.
Vous devez maintenant cloner vcpkg
et dwarfs
:
> cd %HOMEPATH%
> mkdir git
> cd git
> git clone https://github.com/Microsoft/vcpkg.git
> git clone https://github.com/mhx/dwarfs
Ensuite, démarrez vcpkg
:
> .vcpkgbootstrap-vcpkg.bat
Et construisez DwarFS :
> cd dwarfs
> mkdir build
> cd build
> ..cmakewin.bat
> ninja
Une fois cela fait, vous devriez pouvoir exécuter les tests. Définissez CTEST_PARALLEL_LEVEL
en fonction du nombre de cœurs de processeur de votre machine.
> set CTEST_PARALLEL_LEVEL=10
> ninja test
Les bibliothèques et outils DwarFS ( mkdwarfs
, dwarfsck
, dwarfsextract
) sont désormais disponibles sur Homebrew :
$ brew install dwarfs
$ brew test dwarfs
La version macOS du pilote du système de fichiers DwarFS s'appuie sur le génial projet macFUSE. Jusqu'à ce qu'une formule soit ajoutée, vous devrez créer manuellement le pilote DwarFS FUSE.
Construire sur macOS devrait être relativement simple :
Installer Homebrew
Utilisez Homebrew pour installer les dépendances nécessaires :
$ 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
Lors de l'installation de macFUSE pour la première fois, vous devrez autoriser explicitement le logiciel dans Préférences Système / Confidentialité et sécurité . Il est fort probable que vous deviez redémarrer après cela.
Téléchargez une archive tar de version à partir de la page des versions et extrayez-la :
$ 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
de l' brew install
et utiliser ce qui suit à la place de la première commande cmake
ci-dessus : $ 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
C'est ça!
L'astrophotographie peut générer d'énormes quantités de données d'images brutes. Au cours d'une seule nuit, il n'est pas improbable de se retrouver avec quelques dizaines de gigaoctets de données. Avec la plupart des caméras dédiées à l’astrophotographie, ces données se retrouvent sous la forme d’images FITS. Ceux-ci ne sont généralement pas compressés, ne se compressent pas très bien avec les algorithmes de compression standard et, bien qu'il existe certains formats FITS compressés, ceux-ci ne sont pas largement pris en charge.
L'un des formats de compression (simplement appelé « Rice ») se compresse assez bien et est très rapide. Cependant, son implémentation pour les FITS compressés présente quelques inconvénients. Les inconvénients les plus graves sont que la compression n'est pas aussi bonne qu'elle pourrait l'être pour les capteurs de couleur et les capteurs ayant une résolution inférieure à 16 bits.
DwarFS prend en charge la compression ricepp
(Rice++), qui s'appuie sur l'idée de base de la compression Rice, mais apporte quelques améliorations : il compresse nettement mieux les images en couleur et à faible profondeur de bits et recherche toujours la solution optimale pendant la compression au lieu de s'appuyer sur une heuristique. .
Regardons un exemple utilisant 129 images (obscurités, plats et lumières) prises avec un appareil photo ASI1600MM. Chaque image fait 32 Mio, soit un total de 4 Gio de données. Leur compression avec l'outil fpack
standard prend environ 16,6 secondes et donne une taille de sortie totale de 2,2 Gio :
$ time fpack */*.fit */*/*.fit
user 14.992
system 1.592
total 16.616
$ find . -name '*.fz' -print0 | xargs -0 cat | wc -c
2369943360
Cependant, cela vous laisse avec des fichiers *.fz
que toutes les applications ne peuvent pas réellement lire.
En utilisant DwarFS, voici ce que nous obtenons :
$ 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
En moins de 3,4 secondes, il compresse les données à 1,2 Gio, soit près de la moitié de la taille de la sortie fpack
.
En plus d’économiser beaucoup d’espace disque, cela peut également s’avérer utile lorsque vos données sont stockées sur un NAS. Voici une comparaison du même ensemble de données accessibles via une connexion réseau de 1 Gbit/s, en utilisant d'abord les données brutes non compressées :
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
Et ensuite en utilisant une image DwarFS sur le même partage :
$ 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
C'est environ 2,5 fois plus rapide. Vous pouvez très probablement constater des résultats similaires avec des disques durs externes lents.
Actuellement, DwarFS n'a pas de capacité intégrée pour ajouter des informations de récupération à une image du système de fichiers. Cependant, à des fins d'archivage, il est judicieux de disposer de ces informations de récupération afin de pouvoir réparer une image endommagée.
Heureusement, c'est relativement simple en utilisant quelque chose comme par2cmdline :
$ par2create -n1 asi1600-20.dwarfs
Cela créera deux fichiers supplémentaires que vous pourrez placer à côté de l'image (ou sur un autre stockage), car vous n'en aurez besoin que si DwarFS a détecté un problème avec l'image du système de fichiers. S'il y a un problème, vous pouvez exécuter
$ par2repair asi1600-20.dwarfs
qui sera très probablement capable de récupérer l'image si moins de 5% (c'est la valeur par défaut utilisée par par2create
) de l'image sont endommagés.
Les attributs étendus ne sont actuellement pas pris en charge. Les attributs étendus stockés dans le système de fichiers source ne seront actuellement pas conservés lors de la création d'une image DwarFS à l'aide de mkdwarfs
.
Cela étant dit, l'inode racine d'une image DwarFS montée expose actuellement un ou deux attributs étendus sous 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
L'attribut dwarfs.driver.pid
contient simplement le PID du pilote DwarFS FUSE. L'attribut dwarfs.driver.perfmon
contient les résultats actuels de l'analyseur de performances.
De plus, chaque fichier normal expose un attribut dwarfs.inodeinfo
avec des informations sur l'inode sous-jacent :
$ attr -l "05 Disappear.caf"
Attribute "dwarfs.inodeinfo" has a 448 byte value for 05 Disappear.caf
L'attribut contient un objet JSON avec des informations sur l'inode sous-jacent :
$ 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
}
Ceci est utile, par exemple, pour vérifier comment un fichier particulier est réparti sur plusieurs blocs ou quelles catégories ont été attribuées au fichier.
Les tests SquashFS, xz
, lrzip
, zpaq
et wimlib
ont tous été effectués sur un processeur Intel(R) Xeon(R) E-2286M à 8 cœurs à 2,40 GHz avec 64 Go de RAM.
Les tests Cromfs ont été effectués avec une ancienne version de DwarFS sur un processeur Intel(R) Xeon(R) D-1528 à 6 cœurs à 1,90 GHz avec 64 Go de RAM.
Les tests EROFS ont été effectués à l'aide de DwarFS v0.9.8 et EROFS v1.7.1 sur un Intel(R) Core(TM) i9-13900K avec 64 Go de RAM.
Les systèmes étaient pour la plupart inactifs pendant tous les tests.
Le répertoire source contenait 1 139 installations Perl différentes provenant de 284 versions distinctes, soit un total de 47,65 Gio de données dans 1 927 501 fichiers et 330 733 répertoires. Le répertoire source a été récemment décompressé d'une archive tar vers une partition XFS sur un lecteur NVME 970 EVO Plus 2 To, de sorte que la plupart de son contenu était probablement mis en cache.
J'utilise le même type de compression et le même niveau de compression pour SquashFS qui sont le paramètre par défaut pour 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
Pour DwarFS, je m'en tiens aux valeurs par défaut :
$ 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
Ainsi, dans cette comparaison, mkdwarfs
est plus de 6 fois plus rapide que mksquashfs
, à la fois en termes de temps CPU et de temps d'horloge murale.
$ 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
En termes de taux de compression, le système de fichiers DwarFS est plus de 10 fois plus petit que le système de fichiers SquashFS . Avec DwarFS, le contenu a été compressé à moins de 0,9% (!) de sa taille d'origine . Ce taux de compression ne prend en compte que les données stockées dans les fichiers individuels, et non l'espace disque réellement utilisé. Sur le système de fichiers XFS d'origine, selon du
, le dossier source utilise 52 Go, donc l'image DwarFS n'utilise en réalité que 0,8 % de l'espace d'origine .
Voici une autre comparaison utilisant la compression lzma
au lieu de 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
Il est immédiatement évident que les analyses sont nettement plus rapides et que les images résultantes sont nettement plus petites. Pourtant, mkdwarfs
est environ 4 fois plus rapide et produit une image 12 fois plus petite que l'image SquashFS. L'image DwarFS ne représente que 0,6 % de la taille du fichier d'origine.
Alors pourquoi ne pas utiliser lzma
au lieu de zstd
par défaut ? La raison en est que lzma
est environ un ordre de grandeur plus lent à décompresser que zstd
. Si vous n'accédez qu'occasionnellement aux données de votre système de fichiers compressé, cela n'est peut-être pas grave, mais si vous l'utilisez intensivement, zstd
entraînera de meilleures performances.
Les comparaisons ci-dessus ne sont pas tout à fait justes. mksquashfs
utilise par défaut une taille de bloc de 128 Ko, tandis que mkdwarfs
utilise des blocs de 16 Mo par défaut, ou même des blocs de 64 Mo avec -l9
. Lorsque vous utilisez des tailles de blocs identiques pour les deux systèmes de fichiers, la différence, comme on pouvait s'y attendre, devient beaucoup moins dramatique :
$ 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
Même cela n'est toujours pas tout à fait juste, car il utilise une fonctionnalité ( -B3
) qui permet à DwarFS de référencer des morceaux de fichiers provenant d'un maximum de deux blocs de système de fichiers précédents.
Mais le fait est que c'est vraiment là que SquashFS se démarque, car il ne prend pas en charge des tailles de bloc plus grandes ni le référencement arrière. Et comme vous le verrez ci-dessous, les blocs plus gros que DwarFS utilise par défaut n'ont pas nécessairement d'impact négatif sur les performances.
DwarFS propose également une option pour recompresser un système de fichiers existant avec un algorithme de compression différent. Cela peut être utile car cela permet une expérimentation relativement rapide avec différents algorithmes et options sans nécessiter une reconstruction complète du système de fichiers. Par exemple, recompresser le système de fichiers ci-dessus avec la meilleure compression possible ( -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