oxipng: OxiPNG Zopfli compression seems to be overly slow compared to zopflipng's
While using OxiPNG with the Zopfli compression mode, I noticed that some images took an unusually long time to compress. Of course, this is somewhat expected due to the usage of Zopfli compression, which is slow by design. However, some quick benchmarks against zopflipng, with the most similar compression settings possible, showed that zopflipng is both faster and more effective at optimizing images than OxiPNG with Zopfli compression, which is an interesting result.
In particular, to try to get an apples to apples comparison as much as possible, I fixed the following parameters:
- A single thread (because zopflipng is not multithreaded).
- A single filter.
- A fixed number of iterations, 15 (as zopflipng by default changes the number of compression iterations depending on the file size, while OxiPNG always uses 15 iterations).
Of course, I have always used the same unprocessed image, input.png
.
The results were as follows:
$ time target/release/oxipng -v -t1 -f0 -Z input.png
Processing: input.png
2048x2048 pixels, PNG format
4x8 bits/pixel, RGBA
IDAT size = 419799 bytes
File size = 422604 bytes
Trying: 1 combinations
zc = 0 zs = 0 f = 0 399505 bytes
Found better combination:
zc = 0 zs = 0 f = 0 399505 bytes
IDAT size = 399505 bytes (20294 bytes decrease)
file size = 402310 bytes (20294 bytes = 4.80% decrease)
Output: input.png
target/release/oxipng -v -t1 -f0 -Z input.png output.png 513,45s user 0,16s system 99% cpu 8:34,03 total
$ time zopflipng --iterations=15 --filters=0 -y input.png output.png
Optimizing input.png
Input size: 422604 (412K)
Result size: 399568 (390K). Percentage of original: 94.549%
Result is smaller
zopflipng --iterations=15 --filters=0 -y input.png output.png 252,55s user 0,09s system 99% cpu 4:13,16 total
These results show that, for the same input image, zopflipng was 2 times faster than OxiPNG, while also managing to compress the image a bit more.
I believe that these results are interesting, because some quick println!
debugging showed that OxiPNG expends most of its execution time in this function; more exactly, in the zopfli::compress
call:
And both PNG optimization programs use Zopfli for compression, with the zopfli crate being a straightforward translation of the original Zopfli C code to Rust, which should have similar performance (and more quick tests show that the zopfli crate binary has similar performance to compress files to the upstream Zopfli binary). So the compression algorithm itself seems to not be to blame, neither its implementation in Rust, but for some reason OxiPNG still is much more slower than zopflipng, while both programs should end up compressing similar amounts of pixel data.
Has anyone else managed to reproduce this performance difference? What might be causing it?
About this issue
- Original URL
- State: open
- Created 3 years ago
- Reactions: 1
- Comments: 19 (2 by maintainers)
I didn’t try that yet, but I could give it a shot in a few days or so 😄
Thanks for the reminder by the way!
Considering neither carols10cents/zopfli nor dfrankland/zopfli-rs have been updated since 2018, and that zopfli-rs appears to perform slightly better than zopfli, it might be worth switching from zopfli to zopfli-rs. It wouldn’t fix this issue, but it seems like it should give a slight performance improvement.
Big thanks to @AlexTMjugador for the latest zopfli updates! Have you tried running that same
input.png
you mentioned in the first post?Hm, twice as fast. Good luck with the profiling, it would be amazing if you could close that gap 😁
That is… surprising 😯 What happens if you run the result of
-f7
through zopflipng, using--filters=p
to keep the filter?Patch with updated and tested crates (libdeflater, zopfli, clap) is #495
I don’t mind if there are no gains 😃
I thought there was a small improvement already, that’s why I asked for it.
I’m glad to hear you have the issue under your radar, and just ignore my comment above 😃