Zstd: Melhor taxa de compressão se o contexto de compressão for descartado periodicamente

Criado em 8 jul. 2019  ·  3Comentários  ·  Fonte: facebook/zstd

Estou obtendo consistentemente uma taxa de compressão ligeiramente melhor se o contexto de compressão não estiver sendo reutilizado.
Estou criando o contexto de compactação ZSTD e, em seguida, em um loop chamando ZSTD_compressCCtx, cada vez fornecendo 1 MB de buffer com dados. No final do processo, o contexto de compactação é liberado.
Se eu liberar o contexto de compactação e criar um novo antes de prosseguir para compactar o próximo buffer de 1 MB, o tamanho do arquivo de saída será consistentemente cerca de 1% menor.
Outro fato interessante é que a taxa de compressão em torno de 1 - 1,5% melhor se eu estiver usando buffers de entrada de 2 MB com dados, em comparação com buffers de entrada de 1 MB.
No meu caso de uso, não estou limitado pelos recursos de memória.
Questões)

  • É uma prática melhor descartar o contexto de compactação entre compactar grandes blocos de dados?

    • Qual é o tamanho ideal do buffer de entrada recomendado (ou seja, diminuir o tamanho do buffer degradará a taxa de compactação, enquanto o aumento do tamanho do buffer não melhorará a taxa de compactação)?

    • Qualquer maneira de dizer ao zstd "use tanta memória quanto você quiser, mas me dê uma taxa de compressão e / ou velocidade melhor"

    • É realmente compressão de streaming com contexto bom apenas para casos de uso com restrição de memória? Se eu tiver memória suficiente, será melhor compactar de forma independente buffers grandes (> 1 MB)?

question

Todos 3 comentários

Olá @scherepanov ,

este resultado é surpreendente.
Usando ZSTD_compressCCtx() , com a mesma entrada e mesmo nível de compressão, não deve importar (do ponto de vista da taxa de compressão) se o contexto é reutilizado ou não. O único impacto de reutilizar o contexto é economizar tempo de alocação e inicialização, é isso. Se afetar a taxa de compressão, é estranho e provavelmente está errado.

Eu gostaria de reproduzir esse cenário, se possível. Qual versão você está usando ?

É uma prática melhor descartar o contexto de compactação entre compactar grandes blocos de dados?

Você nunca deve precisar descartar o contexto.
O único "bom" motivo para isso é simplificar o código.
Mas, do ponto de vista do desempenho, deve ser apenas benéfico, sem desvantagens.

Qual é o tamanho ideal do buffer de entrada recomendado

Isso é altamente situacional. Não existe um limite "universal".
De modo geral, além do tamanho da janela de 8x, aumentar o tamanho do bloco é cada vez menos valioso.
O tamanho da janela, entretanto, é um valor dinâmico, dependendo do nível de compactação.
Ele varia de 512 KB (nível 1) a 8 MB (nível 19).

Qualquer forma de dizer ao zstd "use quanta memória quiser, mas me dê uma taxa de compressão melhor"

O nível 19 deve ser desse tipo

e / ou velocidade "

O nível 4 é geralmente desse tipo: ele compacta muito rápido, mas usa uma quantidade enorme de memória. É o mais próximo que consigo pensar.

É realmente compressão de streaming com contexto bom apenas para casos de uso com restrição de memória? Se eu tiver memória suficiente, será melhor compactar de forma independente buffers grandes (> 1 MB)?

Compactar / descompactar blocos independentes em uma única passagem ( ZSTD_compressCCtx() e ZSTD_decompressDCtx() ) é simplesmente mais simples e provavelmente tão eficiente quanto pode ser. Se você pode fazer isso, é preferível. O modo de streaming adiciona muita complexidade em cima disso. A complexidade é principalmente interna e oculta, mas a ideia principal é que não pode ser melhor / mais rápida do que a compressão ou descompressão direta de uma passagem.

Obrigado pela resposta muito esclarecedora.
Rastreei diferentes taxas de compressão para diferentes ordens de meus dados. Sim, reutilizar o contexto vs descartar não faz diferença, exatamente como você disse. Desculpe, devo ser mais cuidadoso e investigar mais antes de enviar perguntas.
Seus comentários são muito claros e explicativos. Acho que realmente precisa ser adicionado aos documentos. Especialmente a parte sobre a diferença entre streaming e não streaming - sempre pensei que streaming é mais eficiente, já que você pode construir um dicionário melhor (embora não esteja claro como modificar o dicionário quando os dados mudam em um arquivo). É muito importante compreender claramente que o streaming é praticamente o mesmo que a compressão "baseada em blocos". Por outro lado, o streaming pode ser mais eficiente, pois você lida automaticamente com o tamanho do bloco. Estou usando o tamanho de bloco de 1 MB com o nível de compactação padrão 3 e parece ser insuficiente para obter uma melhor compactação. Desse ponto de vista, o streaming pode ser mais eficiente na taxa de compactação, pois você determinará o tamanho do bloco de maneira mais otimizada. (Isso está correto ???)

streaming é praticamente o mesmo que compressão "baseada em bloco"

Não é exatamente "o mesmo".

Se você cortar os dados de entrada em pedaços e passá-los independentemente para ZSTD_compressCCtx() , você acabará com vários pedaços compactados independentes. Cada pedaço compactado é um _frame_ independente. Eles podem ser descompactados em qualquer ordem, porque cada quadro é independente.

Se você enviar os mesmos dados em um único fluxo, com ZSTD_compressStream() , sem fragmentação, você terminará com um _ único quadro_. Internamente, o frame é cortado em blocos, sim, mas isso não importa, porque os blocos não são independentes. Para decodificar qualquer parte do quadro, é necessário decodificar tudo desde o início.

Em teoria, um único quadro deve ser melhor compactado do que vários quadros independentes. Isso porque cortar dados em vários blocos independentes faz com que perca alguma oportunidade de compactação no início de cada bloco.
No entanto, os modos rápidos são apenas compressores "probabilísticos", que fazem apostas precipitadas para funcionar mais rápido. Nem todas as oportunidades são iguais e, às vezes, selecionar uma oportunidade apenas mascara uma oportunidade melhor posterior. Isso é muito específico aos dados.
Portanto, em alguns casos raros, pode acontecer que o corte de dados em pedaços independentes acabe sendo competitivo com um único fluxo.
Mas eu não apostaria nisso. Na maioria dos casos, o fluxo único deve vencer, mesmo que por pouco.

Esta página foi útil?
0 / 5 - 0 avaliações