.NET / [Из песочницы] Сравнение библиотек для архивации в .Net

в 9:34, , рубрики: .net, zip, метки: , ,

.NET / [Из песочницы] Сравнение библиотек для архивации в .Net
Недавно для моего проекта понадобилась мне библиотека для архивирования. С полгода назад по работе я пользовался библиотекой zlibnet и впечатления остались не очень приятные, так что решил поискать альтернативу. После недолгих поисков наткнулся на обзор библиотек для архивации, которая и сподвигла меня написать этот обзор.
Участники
Я буду тестировать четыре библиотеки: ZLibNet, #ZipLib, DotNetZip и ZipStorer. Теперь о каждой поподробней:
ZLibNet
Лицензия: СвободнаяРазмер: 35 кБ + 137 кБ(ZLib)
Эта библиотека представляет собой обёртку над широко известной сишной библиотекой ZLib. Так как большую часть составляет unmanaged код, то авторы обещают высокую производительность.
Пример кода для архивирования:
  Zipper zip = new Zipper();
  zip.ItemList.Add(inPath);
  zip.ZipFile = outPath;
  zip.PathInZip = enPathInZip.None;
  zip.Zip();

#ZipLib
Лицензия: Модифицированный GPL. Можно использовать в коммерческих проектахРазмер: 196 кБ
Библиотека полностью написана на C#. Заявлена поддержка так же GZip, Tar, BZip2 форматов.
Пример кода для архивирования:
  using (ZipOutputStream s = new ZipOutputStream(File.Create(outPath)))
  {
    s.UseZip64 = UseZip64.Off;
    if (level != -1)
      s.SetLevel(level);
    byte[] buffer = new byte[4096];
    ZipEntry entry = new ZipEntry(Path.GetFileName(inPath));
    s.PutNextEntry(entry);
    using (FileStream fs = File.OpenRead(inPath))
    {
      int sourceBytes;
      do
      {
        sourceBytes = fs.Read(buffer, 0, buffer.Length);
        s.Write(buffer, 0, sourceBytes);
      }
      while (sourceBytes > 0);
    }
    s.Finish();
    s.Close();
  }

DotNetZip
Лицензия: Ms-PlРазмер: 277 кБ(урезанная версия)
Библиотека позиционируется как самая удобная для использования в .net и моно проектах. Заявлена поддержка AES шифрования. Полезным так же может оказаться наличие многих версий: полная, уменьшенная версия(оставлен основной функционал и существенно уменьшен размер), для компакт фреймворка, для SilverLight. Имеется также отдельные версии поддерживающие bzip2 и обёртка на ZLib.
Пример кода для архивирования:
  using (ZipFile zip = new ZipFile())
  {
    zip.CompressionLevel = compressionLevel;
    ZipEntry ze = zip.AddFile(inPath, "");
    zip.Save(outPath);
  }

ZipStorer
Лицензия: Ms-PlРазмер: 33 кБ(исходник)
Строго говоря является не библиотекой, а отдельным классом, в следствии чего крайне просто интегрируется в проект, да и изменения в случае чего произвести будет несложно. Возможности крайне ограничены, но учитывая размер, на это можно закрыть глаза. Старая версия может работать в Silverlight.
Вот вкратце и всё, что можно сказать об испытуемых.
Пример кода для архивирования:
  ZipStorer zip = ZipStorer.Create(outPath, "About");
  zip.AddFile(compressionLevel, inPath, inputFileName, "");
  // Updates and closes the zip file
  zip.Close();

Тестирование

Тестирование будет проводиться следующим образом: делается 100 прогонов каждого метода, измеряется время, убираются 20 худших и 20 лучших времён, по остальным рассчитывается среднее. Платформа: основные тесты проводились на процессоре E8400(3.0GHz) с четырьмя гигабайтами DDRII памяти. Все четыре библиотеки тестируются в одной программе, которая логирует все свои действия и отписывает результаты в csv файл, который потом можно легко открыть в редакторе таблиц. IDE — VS2010. Использовался .net 4.0.
Архивирование

Тесты будут проводиться на 3х файлах: первый — большой текстовый файл, второй — база данных SQLite, и третий — книга «История государства Российского» Карамзина в формате pdf.
Для каждого файла проводятся два теста на первом будут тестироваться все библиотеки с настройками обеспечивающими максимальное быстродействие, на втором будет включено максимальное сжатие, к сожалению функцию уровня сжатия поддерживают только #ZipLib и DotNetZip, поэтому во втором этапе будут участвовать только они.
TXT файл.

Это текстовый файл размером в 9 373 180 байт. Документ по структуре — логи переписки по аське из квипа.
Итак, результаты с максимальной скоростью:
Итак, по скорости #ZipLib и zlibnet одинаковы, однако, вторая библиотека показывает куда лучший результат. Остальные библиотеки показывают серьёзное отставание по скорости. Теперь результаты теста на максимальное сжатие:
Тут результаты более ровные.
DB файл.

База данных, размером 19 407 754 байт. Содержимое базы — большое количество строк.
Ситуация идентична текстовому файлу, теперь результаты теста на максимальное сжатие:
И опять результаты первого тесты повторяются: одна библиотека чуть быстрее, другая немного лучше сжимает.
PDF файл.

ПДФка с отсканированными страницами, размером 19 407 754 байт. Можно ожидать, что сжатие особого толка не даст, однако, давайте это проверим:
Разрывы по размеру оказались несущественны, однако же скорость отличается очень значительно. На этот раз в лидерах ZipStorer, что объяснимо — у него худшее сжатие. DotNetZip и #ZipLib показывают практически одинаковые результаты. Теперь результаты теста на максимальное сжатие:
Ситуация изменилась несильно, разве что, несколько увеличилась разница по времени.
Стоит отметить что изначально название файла содержало кириллицу и только ZipStorer достойно справилась с ним(для этого нужно было добавить строчку: zip.EncodeUTF8 = true), ZlibNet вообще отказалась с ним работать(выбрасывало исключение в котором говорилось что поддерживаются только ASCII символы в названии), а #ZipLib и DotNetZip упаковали странно: стандартный windows просмотрщик показывал пустой архив. Распаковка дала исходный файл, но в названии все кириллические символы были заменены.
Разархивирование.

Для начала я проверил все архивы на чтение. Все библиотеки могут открывать архивы, созданные другими библиотеками, никаких неожиданностей не возникло.
Непосредственно само разархивирование я буду тестировать на двух архивах: первый — база из первого теста запакованная быстрейшим способом, второй — тот же файл, но с ультра сжатием. Оба архива получены с помощью 7-zip. Рассмотрим результаты:
Парадоксально, но факт: все библиотеки распаковывали архив с максимальным сжатием быстрей, чем с минимальным. Удивляют так же гигансткие разрывы между библиотеками.
Сравнение процессоров.

Теперь запущу тест на архивацию тестового файла ещё на двух компьютерах. Первый — годовалый чертырёхядерный i7-870(2.93GHz) 16Gb, и второй — трёхлетний ноутбук Dell 1525 T2370(1.73GHz) 2Gb.
Архивирование базы данных:
Результаты удивляют. Значительный прирост показала только DotNetZip. ZlibNet и ZipStorer показали двухкратный рост производительности при переходе от ноутбука к двухядерному процессору, но вот уже 4х ядерник особого прироста не дал, т.е. можно сделать вывод что они зависят скорее от частоты, чем от количества ядер. Но наиболее поразительным является результат #ZipLib — на i7-870 сжатие занимает больше времени чем на старом ноутбучном процессоре. Объяснить подобную разницу я затрудняюсь.
А вот результаты распаковки архива:
Тут ситуация тоже необычная: и #ZipLib и DotNetZip на i7-870 работают медленней, чем на E8400.
Напоследок, приведу скриншоты диспетчера задач во время работы приложения:
Тут красным выделен период работы ZLibNet, синим — #ZipLib, жёлтым — DotNetZip, и фиолетовым — ZipStorer. Хорошо заметно, что DotNetZip грузит оба ядра на полную катушку. Что и подтверждает результаты теста на сравние.
Итоги.

Тесты получились неоднозначными. У каждой из библиотек имеется свои плюсы и минусы. Лично для себя я выбрал DotNetZip, мне понравился её простой интерфейс и предсказуемый рост производительности относительно мощи процессора.
Исходный код можно посмотреть тут.

Автор: Seekeer


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js