Compactando muitos arquivos grandes semelhantes

18

Tenho centenas de arquivos grandes semelhantes (30 megabytes cada) que desejo compactar. Cada par de arquivos possui 99% dos mesmos dados (menos de 1% de diferença), portanto, espero não ter mais de 40 a 50 megabytes de arquivo.

Único arquivo pode ser comprimido de 30 MB de 13-15 MB (com xz -1, gz -1, bzip2 -1), mas quando comprimir dois ou mais arquivos Quero ter arquivo com tamanho 13-15MB + N*0.3MB, onde N é o número de arquivos.

Ao usar tar(para criar arquivo sólido) e xz -6(para definir o dicionário de compactação como maior que um arquivo - Atualizar - isso não foi suficiente! ), Ainda tenho arquivo com tamanho N*13MB.

Eu acho que ambos gzipe bzip2não vão me ajudar porque eles têm dicionário com menos de 1 MB, e meu fluxo de tar tem repetições a cada 30 MB.

Como arquivar o meu problema no Linux moderno usando ferramentas padrão?

É possível ajustar xza compactação rapidamente, mas use um dicionário com mais de 30 a 60 MB?

Atualização : Fiz o truque com tar c input_directory | xz --lzma2=dict=128M,mode=fast,mf=hc4 --memory=2G > compressed.tar.xz. Não tenho certeza sobre o necessário mf=hc4e as --memory=2Gopções; mas dict=128Mdefina o dicionário para ser grande o suficiente (maior que um arquivo) e mode=fasttorne o processo um pouco mais rápido que -e.

osgx
fonte
A execução xz -1 --memory=2Gnão ajudou, testada em 2 e 4 arquivos do conjunto.
Osgx

Respostas:

12

Dado seus detalhes, presumo que você tenha verificado que seus arquivos realmente têm 99% dos dados em comum, com uma diferença contígua (ou quase contígua) de 1% deles.

Primeiro, você deve usar o tar para criar um arquivo com seus arquivos dentro dele. Para testes, eu criaria um .tar com 10 arquivos, tendo um tamanho de 300MB.

Em seguida, usando xz, você deve configurá-lo para que o dicionário seja maior que o tamanho de um arquivo. Como você não diz se possui restrições de memória, eu usaria xz -9. Não faz sentido não usar toda a memória disponível.

Eu também usaria a predefinição --extreme, para testar se isso faz diferença.

Tamanho do dicionário

Em uma documentação que eu tenho disponível - site - diz-se que o tamanho do dicionário é aproximadamente igual ao uso da memória do descompressor. E o parâmetro -1 significa um ditado de 1MiB, -6 significa 10 MiB (ou 8 MiB em outra parte do mesmo manual). É por isso que você não está obtendo nenhuma vantagem ao ordenar esses arquivos juntos. Usar o -9 tornaria o decompessor (e, portanto, o dicionário) com 64 MiB, e acho que é isso que você deseja.

Editar

Outra possibilidade seria usar outro compressor. Eu usaria o 7zip, mas tarria esses arquivos primeiro e depois os 7ziparia.

Dependendo do conteúdo dos arquivos, talvez você possa usar o 7zip com o método PPM-D (em vez de LZMA ou LZMA2, que é o padrão e o mesmo usado pelo xz)

Não é bom: Zip (dict = 32kB), Bzip (dict = 900 kB).

woliveirajr
fonte
O Xz e o 7-Zip usam o LZMA2, portanto não haveria nenhum benefício lá. O PPMD ​​é otimizado para extração de entropia extremamente lenta, mas com alta taxa de compressão, de mídia já compactada (por exemplo, MP3 e vídeo). Não é particularmente provável encontrar grandes semelhanças entre os dois arquivos e armazená-los no dicionário - não é mais provável que o LZMA2.
allquixotic
woliveirajr, que tal usar not -1ou -9preset, mas especificar dict=64MBor dict=128MBe set mode=fast?
Osgx
Usar dict = xxMB em vez de -1 ou -9 seria direto ao ponto, mas como não sei como o xz define outros parâmetros quando você usa o -9, não sei se você não perderia algo outro. Acho que você está na direção certa, e apenas o teste dará uma resposta precisa.
woliveirajr
3
Com xz --lzma2=dict=128M,mode=fast,mf=hc4 --memory=2Geu era capaz de comprimir 250 arquivos (7,5 GB) para 18 MB arquivo tar.xz.
Osgx
@osgx :) isso é muito bom. Se não demorou muito tempo (isto é, está dentro das suas necessidades), problema resolvido! :) Então você tem final_size = 13MB + x * 6kB, mais ou menos.
woliveirajr
9

Se eles forem realmente 99% semelhantes, como você diz, você poderá usar o bsdiff ou um algoritmo semelhante para calcular as diferenças entre os arquivos. A diferença é cumulativa (ou seja, cada arquivo difere um pouco mais do primeiro) ou a diferença entre dois arquivos é praticamente a mesma?

Se não for cumulativo, você poderá:

  • Tome qualquer arquivo arbitrário como a "linha de base"
  • Execute a bsdiffcomparação do arquivo de linha de base com cada arquivo adicional
  • Armazene cada diff como um arquivo separado, ao lado do arquivo de linha de base
  • Execute um compressor como xznos resultados (a linha de base + as diferenças).

O resultado deve ser muito menor do que apenas xzo arquivo inteiro.

Você pode "reconstituir" os arquivos originais "aplicando" o diff na parte superior da linha de base para obter cada um dos outros arquivos.

allquixotic
fonte
Não cumulativo. ( "Cada par de arquivos têm 99% dos mesmos dados ...")
osgx
1
Se as diferenças não forem cumulativas, essa deve ser uma boa aplicação do bsdiffalgoritmo. De uma chance.
allquixotic
Obrigado pela sua resposta, mas eu já fiz a tarefa com xz: tar c directory|xz --lzma2=dict=128M,mode=faste excluí os arquivos de entrada. Na verdade, meus arquivos de entrada eram texto, então eu posso usar diff em vez de bsdiff(que não está instalado no meu PC).
Osgx #
5

Você (I) pode usar tar com algum arquivador capaz de detectar padrões de longo alcance, por exemplo, rzip ou lrzip ( Leia-me ). Ambos usam detecção / desduplicação de redundância de longo alcance; o rzip usa bzip2 e lrzip usa xz (lzma) / ZPAQ:

O rzip é um programa de compactação, com funcionalidade semelhante ao gzip ou bzip2, mas capaz de tirar proveito de redundâncias de longa distância em arquivos, o que às vezes permite ao rzip produzir taxas de compactação muito melhores do que outros programas. ... A principal vantagem do rzip é que ele possui um buffer de histórico efetivo de 900 Mbyte. Isso significa que ele pode encontrar partes correspondentes do arquivo de entrada em grandes distâncias, em comparação com outros programas de compactação comumente usados. O programa gzip, por comparação, usa um buffer de histórico de 32 kbyte e o bzip2 usa um buffer de histórico de 900 kbyte

O lrzip possui buffer maior e pode usar muitos algoritmos de compactação (muito rápido, rápido, bom e um dos melhores - ZPAQ) após a desduplicação:

O Lrzip usa uma versão estendida do rzip, que faz uma primeira redução de redundância de longa distância. As modificações do lrzip aumentam de acordo com o tamanho da memória.

Os dados são então: 1. Comprimido por lzma (padrão), o que proporciona excelente compactação aproximadamente duas vezes a velocidade da compactação bzip2 ...

Outra maneira é usar o programa bup - backup com desduplicação em nível de bloco / segmento, com base no git packfile:

Ele usa um algoritmo de soma de verificação rolante (semelhante ao rsync) para dividir arquivos grandes em pedaços.

osgx
fonte