chafa icon indicating copy to clipboard operation
chafa copied to clipboard

Performance difference to imgcat

Open torarnv opened this issue 8 months ago • 4 comments

Comparing chafa to imgcat from https://github.com/olivere/iterm2-imagetools/ I'm seeing:

❯ time chafa /tmp/foo.png
chafa /tmp/foo.png  0.14s user 0.14s system 33% cpu 0.805 total

❯ time imgcat /tmp/foo.png
imgcat /tmp/foo.png  0.01s user 0.02s system 16% cpu 0.179 total

And the speed difference is noticeable.

Any idea where the slowdown in chafa comes from? I'd prefer to use chafa for all of its nice options (watching changes to a file e.g.) but the slowdown worries me. Thanks!

torarnv avatar Mar 29 '25 16:03 torarnv

Thanks for bringing it up!

There are two important differences that cause the performance gap. They're both specific to how we implement the iterm protocol:

  • imgcat doesn't decode the input image file, or - as far as I can tell - even check that it is in fact an image. It just sends the raw file data to the terminal wrapped in an escape sequence. Chafa decodes the image and re-emits it as uncompressed TIFF. This is due to our library API taking in-memory image buffers as input. I'd like to avoid handing file data off to the library, because then we'd have to do image loading there too (for the other formats - sixels, kitty, ansi art). It may be possible to bypass the pipeline in simple cases, though, and do it like imgcat then, but we'd have less control over the output, and it could deviate somewhat from that of the other protocols depending on the terminal (e.g. scaling/alignment).
  • Our base64 encoder is extremely rudimentary and slow. This isn't that hard to fix, I just haven't gotten around to it. I think there are fast, minimal implementations out there with compatible licensing we can link with/plug in. PRs welcome!

hpjansson avatar Mar 30 '25 18:03 hpjansson

Thanks for the detailed explanations @hpjansson !

torarnv avatar Mar 31 '25 08:03 torarnv

Having thought about this some, I think the most reasonable improvement would be to improve the base64 encoder and call it a day. I think it could be made 10x-20x faster.

For PNG decoding, both programs have to do it somewhere between reading the file and displaying it on screen - imgcat just offloads this job on the terminal and exits. Since it happens in the terminal's process, it's not included in the time measurement.

You may be able to get a more accurate benchmark by sending a big batch of images (>100) in a single invocation, causing the terminal to stall out in the decoding step. imgcat will still come out ahead because of the superior base64 implementation, Chafa's TIFF encoding (I don't know how much this accounts for - I made it uncompressed to add as little overhead as possible) and the fact that imgcat can still exit a bit before the terminal is done decoding. Though if the terminal processes input asynchronously, it could decide to just drop images as it realizes they'll scroll out anyway, which would ruin the comparison.

Another way to try to isolate the overhead added by Chafa would be to test with a more lightweight file format - QOI is a good one, as is XWD, (uncompressed) TIFF and perhaps GIF.

hpjansson avatar Mar 31 '25 22:03 hpjansson