سرعة الالتواء المكررة هي نظام ملفات متقدم للقراءة فقط.
نظام ملفات سريع وعالي الضغط للقراءة فقط لنظامي التشغيل 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، ثم قمت ببعض عمليات التنظيف وإصلاح الأخطاء وإعادة البناء بين الحين والآخر، لكنني لم أوصلها أبدًا إلى الحالة التي أشعر فيها بالسعادة لإصدارها. لقد كان البناء محرجًا للغاية مع اعتماده على مكتبة Facebook الحمقاء (الرائعة جدًا) ولم يكن لديه أي وثائق.
ومع حفر المشروع مرة أخرى هذا العام، لم تبدو الأمور قاتمة كما كانت من قبل. يتم إنشاء Folly الآن باستخدام CMake ولذلك قمت بسحبه كوحدة فرعية. يمكن تلبية معظم التبعيات الأخرى من الحزم التي ينبغي أن تكون متاحة على نطاق واسع. ولقد كتبت بعض المستندات البدائية أيضًا.
يجب عادةً إنشاء DwarFS بشكل جيد مع الحد الأدنى من التغييرات خارج الصندوق. إذا لم يحدث ذلك، يرجى رفع قضية. لقد قمت بإعداد وظائف CI باستخدام صور Docker لـ Ubuntu (22.04 و24.04) وFedora Rawhide وArch التي يمكن أن تساعد في تحديد مجموعة محدثة من التبعيات. لاحظ أن البناء من كرة tarball الخاصة بالإصدار يتطلب تبعيات أقل من البناء من مستودع git، لا سيما أن أداة ronn
وكذلك Python ووحدة mistletoe
Python ليست مطلوبة عند البناء من كرة tarball الخاصة بالإصدار.
هناك بعض الأشياء التي يجب أن تكون على دراية بها:
هناك ميل لمحاولة تفكيك مكتبات 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 driver) في ملف واحد قابل للتنفيذ. يتم ضغط هذه الملفات التنفيذية باستخدام 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
، يعتمد ثنائي Windows العالمي على winfsp-x64.dll
من مشروع WinFsp. ومع ذلك، بالنسبة للثنائي العالمي، يتم تحميل ملف DLL ببطء، لذا لا يزال بإمكانك استخدام كافة الأدوات الأخرى بدون ملف DLL. راجع قسم دعم Windows لمزيد من التفاصيل.
يستخدم DwarFS CMake كأداة بناء.
يستخدم كلاً من Boost و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
.
من الممكن أيضًا إنشاء/تثبيت مكتبات وأدوات 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
اختياريين، لكنهما يساعدان في التجميع السريع.
اعتمادًا على توزيعتك، ستحتاج إلى إنشاء إصدارات ثابتة من بعض المكتبات وتثبيتها، على سبيل المثال 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 للقراءة فقط.
يمكن العثور على وصف لتنسيق نظام ملفات DwarFS بتنسيق dwarfs.
يتم عرض نظرة عامة عالية المستوى على التشغيل الداخلي لـ 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) قبل أن يصل هذا المشروع إلى الإصدار 1.0.0.
دعم نظام التشغيل Windows تجريبي حاليًا. بعد أن عملت حصريًا إلى حد كبير في عالم Unix على مدار العقدين الماضيين، فإن تجربتي في تطوير Windows محدودة نوعًا ما وأتوقع أن يكون هناك بالتأكيد أخطاء وحواف خشنة في كود Windows.
يعتمد إصدار Windows لبرنامج تشغيل نظام الملفات DwarFS على مشروع 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
يعتمد إصدار 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
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 مضغوطة معينة، إلا أنها غير مدعومة على نطاق واسع.
أحد تنسيقات الضغط (يسمى ببساطة "Rice") يضغط بشكل جيد وسريع حقًا. ومع ذلك، فإن تطبيقه لـ 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
مع معلومات حول inode الأساسي:
$ attr -l "05 Disappear.caf"
Attribute "dwarfs.inodeinfo" has a 448 byte value for 05 Disappear.caf
تحتوي السمة على كائن JSON يحتوي على معلومات حول inode الأساسي:
$ 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
على وحدة معالجة مركزية Intel(R) Xeon(R) E-2286M ذات 8 نواة بسرعة 2.40 جيجاهرتز وذاكرة وصول عشوائي (RAM) تبلغ 64 جيجا بايت.
تم إجراء اختبارات Cromfs باستخدام إصدار أقدم من DwarFS على وحدة المعالجة المركزية Intel(R) Xeon(R) ذات 6 نواة 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 على محرك أقراص 970 EVO Plus 2TB NVME، لذلك من المحتمل أن تكون معظم محتوياته مخزنة مؤقتًا.
أنا أستخدم نفس نوع الضغط ومستوى الضغط لـ 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