On Fri, 2 Jan 2026 02:34:55 GMT, Jeremy Wood <[email protected]> wrote:

>> When decoding an uninterlaced 8-bit PNG image, the PNGImageDecoder is 
>> basically copying one byte at a time.
>> 
>> This PR uses System.arraycopy instead, and it shows approx a 10% improvement.
>> 
>> This graph shows the time it takes different decoders to convert a byte 
>> array into a BufferedImage as the size of the PNG image increases:
>> 
>> <img width="596" height="366" alt="Screenshot 2025-12-27 at 9 14 19 PM" 
>> src="https://github.com/user-attachments/assets/73583cb2-eda0-47a8-b818-735a1835f1e8";
>>  />
>> 
>> (This originally came to my attention when looking at an image in Java 1.8. 
>> There the ImageConsumer model took approx 400% longer than ImageIO. I was 
>> happy to see in recent JDKs that gap narrowed significantly, but there was 
>> still a noticeable 10% discrepancy.)
>> 
>> I haven't tried submitting a performance enhancement PR before; I'm not sure 
>> if this issue meets this group's threshold for being worth addressing. And 
>> if it does: I'm not sure how to structure a unit test for it.
>
> Jeremy Wood has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   8374377: test correctness of non-interlaced PNGs too
>   
>   Also this removes the performance comparison. (As of this writing there's a 
> separate 
> `test/micro/org/openjdk/bench/sun/awt/image/PNGImageDecoder_8bit_uninterlaced.java`
>  file used to demonstrate that this change is more performant.)

The change in `PNGImageDecoder` makes sense to me, although I haven't had a 
chance to run the JMH benchmark locally on my end.

test/jdk/sun/awt/image/png/PNGImageDecoder_8bit_performance.java line 60:

> 58:  * This test has never failed.
> 59:  */
> 60: public class PNGImageDecoder_8bit_performance {

Since this is now purely a regression test and the performance aspect has been 
removed, perhaps rename to e.g. `PngImageDecoder8BitTest`?

test/jdk/sun/awt/image/png/PNGImageDecoder_8bit_performance.java line 174:

> 172:             BufferedImage actual = models[1].load(imageData);
> 173: 
> 174:             testCorrectness(expected, actual);

Am I correct in assuming that both models end up using `PNGImageDecoder` under 
the covers? If so, won't `expected` and `actual` always match, even if there is 
a bug in `PNGImageDecoder`? I wonder if it would be better to keep the original 
`BufferedImage` around (the one we draw on), use it as `expected`, and compare 
it to the two model-generated images.

test/jdk/sun/awt/image/png/PNGImageDecoder_8bit_performance.java line 233:

> 231:                                         BufferedImage actual) {
> 232:         if (expected.getWidth() != actual.getWidth()) {
> 233:             throw new Error();

Probably better to throw a `RuntimeException` instead of an `Error` here and 
below (at least that seems to be the convention that I've seen elsewhere). Also 
always best to include a short error message that helps zero in on the exact 
issue if it ever fails.

test/jdk/sun/awt/image/png/PNGImageDecoder_8bit_performance.java line 243:

> 241:                 int argb2 = actual.getRGB(x, y);
> 242:                 if (argb1 != argb2) {
> 243:                     throw new Error("x = " + x + ", y = " + y);

`Error` -> `RuntimeException`, and I'd probably also include the two colors 
that didn't match in the message

test/micro/org/openjdk/bench/sun/awt/image/PNGImageDecoder_8bit_uninterlaced.java
 line 76:

> 74:     @Benchmark
> 75:     public void measurePNGImageDecoder(Blackhole bh) throws Exception {
> 76:         Image img = Toolkit.getDefaultToolkit().createImage(pngImageData);

Does the `BufferedImage` need to be created this way, or could it be simplified 
down to a simple `ImageIO.read()` with a `ByteArrayInputStream`?

test/micro/org/openjdk/bench/sun/awt/image/PNGImageDecoder_8bit_uninterlaced.java
 line 172:

> 170:      * any accuracy.
> 171:      */
> 172:     private static void testCorrectness(BufferedImage expected,

Should the correctness check in the JMH benchmark be removed, since that's 
handled in the unit test?

-------------

PR Review: https://git.openjdk.org/jdk/pull/29004#pullrequestreview-3623125208
PR Review Comment: https://git.openjdk.org/jdk/pull/29004#discussion_r2657759447
PR Review Comment: https://git.openjdk.org/jdk/pull/29004#discussion_r2657780639
PR Review Comment: https://git.openjdk.org/jdk/pull/29004#discussion_r2657765027
PR Review Comment: https://git.openjdk.org/jdk/pull/29004#discussion_r2657763413
PR Review Comment: https://git.openjdk.org/jdk/pull/29004#discussion_r2657722294
PR Review Comment: https://git.openjdk.org/jdk/pull/29004#discussion_r2657715697

Reply via email to