OpenImageIO/oiio — pull request #491 by lgritz (2013-01-23 07:24:51+00:00)
Title: Performance fixes

1. Several more places where there are std::vector<> used for basic temporary memory management, changed to boost::scoped_array (automatically frees upon destruction, but doesn't clear the memory upon allocation).

2. Improve performance in all sorts of places by cleaning up convert_types:
* Don't use tmp scratch space for nonfloat->float case (just do a direct convert from buffer to buffer)
* If you must use scratch space, use stack if small, heap only if big.
* Rearrange switch cases to have common ones first, impossible ones never.
* Drop useless parameters (but provide one of the old signature for link compatibility).

Between these two sets of changes (but mainly the second one), there are dramatic improvements in file reading time.

Before, as measured by imagespeed_test:

Reading a 4096x4096 uint8 4-channel tif:
read_image : 1.43s = 11.8 Mpel/s
ImageBuf read : 1.66s = 10.1 Mpel/s
ImageCache get_pixels : 1.51s = 11.1 Mpel/s
ImageBuf read (autotile) : 1.63s = 10.3 Mpel/s
ImageCache get_pixels (autotile) : 1.52s = 11.0 Mpel/s

Reading a 4096x4096 half 4-channel exr:
read_image : 4.05s = 4.1 Mpel/s
ImageBuf read : 4.46s = 3.8 Mpel/s
ImageCache get_pixels : 4.30s = 3.9 Mpel/s
ImageBuf read (autotile) : 4.45s = 3.8 Mpel/s
ImageCache get_pixels (autotile) : 4.27s = 3.9 Mpel/s

After this patch:

Reading a 4096x4096 uint8 4-channel tif:
read_image : 0.73s = 23.0 Mpel/s
ImageBuf read : 0.99s = 17.0 Mpel/s
ImageCache get_pixels : 0.82s = 20.5 Mpel/s
ImageBuf read (autotile) : 0.93s = 18.0 Mpel/s
ImageCache get_pixels (autotile) : 0.82s = 20.4 Mpel/s

Reading a 4096x4096 half 4-channel exr:
read_image : 2.29s = 7.3 Mpel/s
ImageBuf read : 2.68s = 6.3 Mpel/s
ImageCache get_pixels : 2.29s = 7.3 Mpel/s
ImageBuf read (autotile) : 2.56s = 6.5 Mpel/s
ImageCache get_pixels (autotile) : 2.38s = 7.0 Mpel/s

So, within some measurement error, this patch almost doubles file-reading performance across several different methods of reading images with OIIO. I expect these to speed up other operations, not just file reads, but this is a convenient (and not unimportant) thing to measure as an example.

This does not change APIs in an incompatible way, so I'd like to back-port to 1.1 so that production users can get the benefit immediately.

(The reason why, generally, the OpenEXR files read slower than TIFF is probably because of the uint8 versus 'half' -- it's twice as much data to read from disk and move around in memory, and also a more expensive conversion to float.)