JDK-6354056 : JPEGImageReader could be optimized
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.imageio
  • Affected Version: 5.0
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: solaris_9
  • CPU: generic
  • Submitted: 2005-11-22
  • Updated: 2008-02-05
  • Resolved: 2005-12-05
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6
6 b63Fixed
Description
In imageioJPEG.c, we read one scanline at a time, then copy the decoded data into
a temporary buffer before stuffing it into the destination raster.  That intermediate
copy step is currently not as efficient as possible since it copies one byte at a
time, but in the common case (where jpeg_read_scanlines() produces 3ByteRgb data)
the component data is already ordered, so we could simply use memcpy() instead.

Comments
EVALUATION See suggested fix. This change is especially beneficial on solaris-sparc (results taken on SB2000, 900 MHz USIII, 1GB RAM, -client, -Xms256M -Xmx512M, "base" is the 2005-11-19.mustang 2D nightly build, "test" is similar but contains the changes described here): Options common across all tests: testname=imageio.input.image.imageio.reader.tests.read imageio.input.image.imageio.reader.opts.ignoreMetadata=true imageio.input.opts.general.source=file imageio.input.image.imageio.opts.format=core-jpg imageio.input.image.imageio.reader.opts.installListener=false imageio.input.image.imageio.reader.opts.seekForwardOnly=true imageio.input.opts.imageio.useCache=false imageio.opts.content=photo imageio.opts.size=1000: base: 3874.603733 (var=0.51%) (100.0%) test: 5756.207674 (var=29.19%) (148.56%) imageio.opts.size=250: base: 3591.873386 (var=5.87%) (100.0%) test: 5702.289632 (var=2.83%) (158.76%) imageio.opts.size=4000: base: 1893.939393 (var=4.89%) (100.0%) test: 4356.112169 (var=11.39%) (230.0%) This fix has less dramatic results on other platforms, such as solaris-i586 (results taken on W2100z, 2x 2.0 GHz Opteron, 2GB RAM, same options as above): imageio.opts.size=1000: base: 13322.61398 (var=0.35%) (100.0%) test: 14672.16872 (var=0.16%) (110.13%) imageio.opts.size=250: base: 12019.48888 (var=0.72%) (100.0%) test: 13075.79003 (var=0.6%) (108.79%) imageio.opts.size=4000: base: 11624.52775 (var=0.25%) (100.0%) test: 12779.55271 (var=0.19%) (109.94%) And on windows-i586 (results taken on 2x 2.8 GHz P4, 1GB RAM, same options as above): imageio.opts.size=1000: base: 16494.39190 (var=0.0%) (100.0%) test: 17877.92235 (var=0.17%) (108.39%) imageio.opts.size=250: base: 13722.69184 (var=0.69%) (100.0%) test: 14741.27557 (var=0.16%) (107.42%) imageio.opts.size=4000: base: 15581.52476 (var=0.43%) (100.0%) test: 17467.24890 (var=0.42%) (112.1%)
22-11-2005

SUGGESTED FIX *** /tmp/geta1993 Mon Nov 21 19:19:19 2005 --- imageioJPEG.c Thu Nov 10 15:49:37 2005 *************** *** 1764,1769 **** --- 1764,1770 ---- int maxBandValue, halfMaxBandValue; boolean mustScale = FALSE; boolean progressive = FALSE; + boolean orderedBands = TRUE; imageIODataPtr data = (imageIODataPtr) ptr; j_decompress_ptr cinfo; *************** *** 1812,1817 **** --- 1813,1821 ---- for (i = 0; i < numBands; i++) { bands[i] = body[i]; + if (orderedBands && (bands[i] != i)) { + orderedBands = FALSE; + } } (*env)->ReleaseIntArrayElements(env, srcBands, body, JNI_ABORT); *************** *** 1974,1979 **** --- 1978,1991 ---- *out++ = data->scale[i][*(in+bands[i])]; } } + } else if (orderedBands && (pixelStride == numBands)) { + // Optimization: The component bands are ordered sequentially, + // so we can simply use memcpy() to copy the intermediate + // scanline buffer into the raster. + in = scanLinePtr + (sourceXStart * cinfo->num_components); + if (pixelLimit > in) { + memcpy(out, in, pixelLimit - in); + } } else { for (in = scanLinePtr+sourceXStart*cinfo->num_components; in < pixelLimit;
22-11-2005