After many years frustrated with how slow Common Lisp's png-read library is, I decided to take an evening to try to optimize it. Here are the timing results of trying to parse a file from disk 1000 times with SBCL 1.3.19, for each of these sample images in PNGSuite.
Format | Original | Modified | Ratio |
---|---|---|---|
Grayscale 1bit | 0.190s | 0.117s | 1.62x |
Grayscale 2bit | 0.117s | 0.077s | 1.52x |
Grayscale 4bit | 0.119s | 0.094s | 1.27x |
Grayscale 8bit | 0.201s | 0.118s | 1.70x |
Grayscale 16bit | 0.287s | 0.203s | 1.41x |
Grayscale/Alpha 8bit | 0.426s | 0.191s | 2.23x |
Grayscale/Alpha 16bit | 0.946s | 0.559s | 1.69x |
Indexed 1bit | 0.202s | 0.163s | 1.24x |
Indexed 2bit | 0.217s | 0.187s | 1.16x |
Indexed 4bit | 0.221s | 0.199s | 1.11x |
Indexed 8bit | 0.267s | 0.265s | 1.01x |
RGB 8bit | 0.765s | 0.283s | 2.70x |
RGB 16bit | 1.291s | 0.453s | 2.85x |
RGBA 8bit | 1.035s | 0.335s | 3.09x |
RGBA 16bit | 1.848s | 0.722s | 2.56x |
Particularly noticeable are the RGB and RGBA variants, with an approximate 3x boost. I may continue to optimize more, but for a start I am definitely happier.
Update 2017-08-07: Changes have been merged upstream, so everyone can take advantage of the performance boost in the original version later this month when the latest Quicklisp dist is released.
Update 2017-08-24: I wrote a PNG parser completely from scratch, called pngload, that is even faster, and more featureful. Check it out here.