Как выполнить многопоточное сжатие / распаковку с помощью GZipStream без промежуточных файлов при очень большом вводе - PullRequest
0 голосов
/ 08 мая 2018
  • Я хочу написать программу, которая выполняет многопоточное сжатие / распаковку с использованием NET 3.5 и библиотеки GZipStream.

  • Входные файлы очень большие (скажем, сотни гигабайт)

  • Я бы хотел добиться этого без каких-либо промежуточных файлов. Это был мой первоначальный подход, но требования изменились.

Я думал о следующих подходах и хотел бы проверить, хорошо ли это выглядит на бумаге:

  1. Чтение из исходного файла и разбиение его на фрагменты постоянного размера в памяти.

  2. Отслеживайте количество потоков, поскольку у нас ограничена память.

  3. Каждый блок сжимается в памяти отдельным потоком.

  4. Эти сжатые блоки помещаются в очередь в правильном порядке.

  5. Существует один поток, который читает из очереди и объединяет ее в выходной файл.

  6. Также храните где-нибудь метаданные о сжатых чанках, которые будут помещены позже в заголовок. Я хотел бы использовать это для декомпрессии.

Сделав вышеизложенное, моя идея многопоточной декомпрессии была бы тогда:

  1. Чтение файла метаданных о соединенных фрагментах.

  2. Считать данные из сжатого файла в виде фрагментов, определенных метаданными.

  3. Каждый блок распаковывается отдельным потоком в памяти.

  4. Эти распакованные фрагменты добавляются в очередь в правильном порядке.

  5. Существует поток, который объединяет распакованные фрагменты в единый выходной файл.

Вышеуказанное кажется правдоподобным?

Ответы [ 3 ]

0 голосов
/ 08 мая 2018

Да, когда вы рассматриваете каждый блок как отдельный элемент (он получает собственный поток GZip), это должно работать. Но это добавит некоторые накладные расходы, ваше общее сжатие будет немного ниже.

Для каждого фрагмента вам потребуется размер и порядковый номер для десериализации и повторной последовательности.
В любом случае получатель должен будет выполнить повторную последовательность, чтобы вы могли пропустить это на отправителе.

Но трудно оценить, сколько вы выиграете от этого, сжатие немного загружает процессор, но все же намного быстрее, чем большинство устройств ввода-вывода.

0 голосов
/ 08 мая 2018

Конечно, это будет работать нормально. Как это происходит, объединение действительных файлов GZIP также является действительным файлом GZIP. Каждый отдельный разжимаемый поток называется членом gzip. Ваши метаданные просто нуждаются в смещении в файле для начала каждого потока.

Дополнительный блок заголовка gzip ограничен 64 Кбайтами, так что это может ограничивать размер блока, например порядка десятков до ста мегабайт. По другой причине я бы порекомендовал, чтобы ваши куски данных в любом случае сжимались не менее нескольких мегабайт каждый - во избежание снижения эффективности сжатия.

Недостатком конкатенации является то, что вы не получаете полной проверки целостности ввода. Например, если вы каким-либо образом испортили порядок членов, это не будет обнаружено при распаковке, поскольку проверка целостности каждого члена будет проходить независимо от порядка. Поэтому вы можете включить общую проверку несжатых данных. Примером может быть CRC всех несжатых данных, которые могут быть вычислены из CRC членов с использованием zlib's crc32_combine().

Мне было бы интересно узнать, если в вашем случае вы получаете значительное ускорение от параллельной декомпрессии. Декомпрессия обычно достаточно быстрая, так что она связана с вводом / выводом на запоминающем устройстве большой емкости.

0 голосов
/ 08 мая 2018

Я не думаю, что GZip может быть разбит таким образом. Весь поток зависит от некоторого словаря токенов ( дерево Хаффмана или вариация) в начале. Как подсказка, GZipStream.CanSeek() всегда возвращает false.

Таким образом, ваш пункт 3. потерпит неудачу - куски не являются независимыми.

Что может сработать, это обрабатывать 2 или даже 3 файла параллельно, в зависимости от вашего оборудования ввода / вывода. Больше подходит для быстрого SSD, чем для старого HDD. Сетевой ввод-вывод обычно квалифицируется как медленный жесткий диск.

...