Otimização do Zopfli: Largura de banda literalmente gratuita

Em 2007, escrevi sobre usando o PNGout para produzir imagens PNG incrivelmente pequenas. Ainda me refiro a esse tópico com frequência, pois, sete anos depois, é muito improvável que o PNG médio que encontro na Internet seja otimizado.

Por exemplo, considere o seguinte este recente desenho animado da Perry Bible Fellowship.

Salvo diretamente do site do PBF, esse quadrinho é uma imagem PNG colorida de 800 × 1412, 32 bits, com 671.012 bytes. Vamos salvá-la em alguns formatos diferentes para ter uma ideia de quanto espaço essa imagem pode ocupar:

BMP 24 bits 3,388,854
BMP 8 bits 1,130,678
GIF 8 bits, sem dither 147,290
GIF 8 bits, dither máximo 283,162
PNG 32 bits 671,012

O PNG é uma vitória porque, assim como o GIF, ele tem compactação integrada, mas ao contrário do GIF, o senhor não está limitado a imagens de 8 bits e 256 cores. Agora, o que acontece quando aplicamos o PNGout a essa imagem?

PNG padrão 671,012
PNGout 623,859 7%

Pegue qualquer PNG aleatório de procedência desconhecida, aplique o PNGout e o senhor provavelmente verá uma economia de cerca de 10% no tamanho do arquivo, possivelmente muito mais. Lembre-se, isso é sem perdas compressão. O resultado é idêntico. É um arquivo menor para ser enviado pelo cabo, e quanto menor o arquivo, mais rápida é a descompressão. Isso é largura de banda livrePessoal! Não há nada melhor do que isso!

Exceto quando fica.

Em 2013, o Google introduziu um novo método de compactação totalmente compatível com as versões anteriores que eles chamam de Zopfli.

A saída gerada pelo Zopfli é tipicamente 3-8% menor em comparação com o zlib com compressão máxima, e acreditamos que o Zopfli representa o estado da arte em compressão compatível com Deflate. O Zopfli foi escrito em C para facilitar a portabilidade. É uma biblioteca somente de compactação; o software existente pode descompactar os dados. O Zopfli é compatível com a compressão de fluxo de bits usada em gzip, Zip, PNG, solicitações HTTP e outros.

Peço desculpas por estar super atrasado para essa festa, mas vamos testar essa afirmação ousada. O que acontece com nosso quadrinho PBF?

PNG padrão 671,012
PNGout 623,859 7%
ZopfliPNG 585,117 13%

Parece bom. Mas essa é apenas uma imagem. Estamos grandes fãs de Emoji no Discoursevamos testá-lo na primeira versão original do Emoji One conjunto de emojis – esse é um conjunto completo de 842 arquivos PNG de 64×64 em cores de 32 bits:

PNG padrão 2,328,243
PNGout 1,969,973 15%
ZopfliPNG 1,698,322 27%

Uau. O senhor quer um pouco disso.

Em meus testes, o Zopfli produz de forma confiável imagens PNG de 3 a 8% menores do que até mesmo o poderoso PNGout, o que é um feito incrível. Além disso, qualquer recurso compactado com gzip padrão pode se beneficiar do deflate aprimorado do Zopfli, como o jQuery:

Ou os testes de corpus de compressão padrão:

gzip -­9 kzip Zopfli
Alexa 10k 128mb 125mb 124mb
Calgary 1017kb 979kb 975kb
Canterbury 731kb 674kb 670kb
enwik8 36mb 35mb 35mb

(Curiosamente, eu não tinha ouvido falar do kzip – parece que esse é o nosso velho amigo Ken Silverman aparecendo novamente, provavelmente usando o mesmo conjunto de truques de compactação de seu utilitário PNGout).

Mas há um problema, pois o sempre há uma pegadinha – é também 80 vezes mais lento. Não, isso não é um erro de digitação. Sim, o senhor leu certo.

gzip -­9 5.6s
7­zip ­mm=Deflate ­mx=9 128s
kzip 336s
Zopfli 454s

A compactação Gzip é mais rápida do que parece na comparação acima, porque o nível 9 é um pouco lento para o que faz:

Tempo Tamanho
gzip -1 11.5s 40.6%
gzip -2 12.0s 39.9%
gzip -3 13.7s 39.3%
gzip -4 15.1s 38.2%
gzip -5 18.4s 37.5%
gzip -6 24.5s 37.2%
gzip -7 29.4s 37.1%
gzip -8 45.5s 37.1%
gzip -9 66.9s 37.0%

O senhor decide se essa enorme diferença de 0,1% na taxa de compressão entre o gzip -7e gzip -9 vale a pena o duplicação no tempo de CPU. Em notícias relacionadas, é por isso que praticamente todos os níveis ou modos de compactação “Ultra” das ferramentas de compactação são geralmente uma má ideia. O senhor cai em um precipício algorítmico muito rapidamente, portanto, mantenha-se no meio ou na parte ideal da curva, que tende a ser o nível de compactação padrão. Eles escolhem esses padrões por um motivo.

O PNGout não era exatamente rápido para começar, portanto, imaginar algo que seja 80 vezes mais lento (na melhor das hipóteses!) para compactar uma imagem ou um arquivo é definitivamente motivo de preocupação. Talvez o senhor não perceba em imagens pequenas, mas tente executá-las em um PNG maior e, basicamente, será hora de comer um sanduíche. Ou, se o senhor tiver uma CPU com vários núcleos, de 4 a 16 sanduíches. É por isso que aplicar o Zopfli a imagens carregadas pelo usuário pode não ser a melhor ideia, pois o primeiro servidor que tentar usar o Zopfli em uma imagem PNG de 10k × 10k terá uma grande surpresa.

Entretanto, lembre-se de que o descompressão continua na mesma velocidade e é totalmente segura. Isso significa que o senhor provavelmente só vai querer usar o Zopfli em recursos pré-compiladosque são projetados para serem compactados uma vez e baixados milhões de vezes, em vez de um monte de imagens PNG que seus usuários carregaram e que podem ser visualizadas apenas algumas centenas ou milhares de vezes, na melhor das hipóteses, independentemente da otimização das imagens.

Por exemplo, em Discurso temos um renderizador de avatar padrão que produz avatares PNG de boa aparência para os usuários com base na primeira letra de seu nome de usuário, além de um esquema de cores selecionado por meio do hash de seu nome de usuário. Ah, sim, e o muito bom Fonte de código aberto Roboto do Google.

Passamos um muito de tempo otimizando as imagens de avatar de saída, porque esses avatares podem ser servidos milhões de vezes, e pré-renderizando todos eles, dadas as restrições de …

  • 10 números
  • 26 letras
  • ~250 esquemas de cores
  • ~5 tamanhos

… não é irracional, com cerca de 45.000 arquivos exclusivos. Também temos uma CDN https centralizada que configuramos para servir avatares (se desejado) em todas as instâncias do Discourse, para reduzir ainda mais a carga e aumentar os acessos ao cache.

Como essas imagens se limitam a tons de uma cor, reduzi a paleta de cores para 8 bits (na verdade, 128 cores) para economizar espaço e, é claro, executamos o PNGout nos arquivos resultantes. Eles são tão pequenos quanto o senhor pode obter. Quando executei o Zopfli nos avatares acima, fiquei muito empolgado ao ver a redução esperada de 3 a 8% no tamanho do arquivo livre e, após a execução dos comandos do console, vi que foram economizados… 1 byte, 5 bytes e 2 bytes, respectivamente. Trombone triste.

(Sim, é tecnicamente possível produzir imagens PNG estranhas com “perdas”, mas acho que isso vai contra o espírito do PNG, que foi projetado para sem perdas imagens. Se o senhor quiser imagens com perdas, opte por JPG ou outro formato com perdas).

O melhor do Zopfli é que, supondo que o senhor não se importe com as demandas iniciais extremas de CPU, ele é uma etapa de otimização do tipo “configure e esqueça” que pode ser aplicada em qualquer lugar e nunca o prejudicará. Bem, a não ser pela possibilidade de queimar muitos ciclos sobressalentes da CPU.

Se o senhor trabalha em um projeto que serve ativos compactados, dê uma olhada no Zopfli. Não é uma bala de prata – como em todos os conselhos, execute os testes no o senhor e veja – mas é o mais próximo que o senhor pode chegar largura de banda literalmente livre em nossa linha de trabalho.