[
https://issues.apache.org/jira/browse/IMAGING-356?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17743841#comment-17743841
]
Gary Lucas commented on IMAGING-356:
------------------------------------
Gary,
I think you are correct in identifying ImageBuilder.setRGB() as a bottleneck.
The setRGB method is called to populate each pixel in an image one-at-a-time.
I will look at what would be required to implement a method that populated a
set of multiple pixels (perhaps one row at a time).
The current version uses the Java Math.multiplyExact and Math.addExact methods
to perform exact arithmetic in an effort to avoid integer overflow. Of course,
integer overflow is a condition that will "never" happen... The elements
involved, image width and x/y coordinates should be well within the range of
normal integer arithmetic. And if they're not, then something else will break
long before setRGB is called. Even so, I am not strongly advocating changing
setRGB back to the form I originally implemented.
Just to gain insights, I looked at reverting the code back to its original form.
The current code looks something like:
{code:java}
final int rowOffset = Math.multiplyExact(y, width);
final int index = Math.addExact(rowOffset, x);
if (index > data.length) {
throw new IllegalArgumentException("setRGB: Illegal array index.");
}
data[index] = argb;{code}
I tried refactoring it two ways (bare bones):
{code:java}
data[y * width + x] = argb;{code}
And range checked
{code:java}
final int index = y * width + x;
if(0<=index && index<data.length){
data[index] = argb;
}else{
throw new IllegalArgumentException("setRGB: Illegal array index.");
}{code}
And, finally, I also tried it by making the code a no-operation. This would be
useless for normal operations, of course, but it gives some idea of how much
the millions of separate calls are costing us.
Timing values for the three approaches using the Speed-and-Memory test are
given below. My PC is a very noisy test environment, so I needed to repeat
these several times to get reliable numbers.
"Exact" math: 22.747 ms
Range checked: 21.732
Bare Bones: 20.432
No operation: 17.712
So as you can see, we can improve throughput by switching over to the
range-checked method (which would be sufficient to capture any integer overflow
events), but the payoff would be modest. Even the bare bones form is only
about a 10 percent improvement over the current approach.
The fact that the "no operation" method takes as long as it does suggests that
the big performance sink isn't so much the internals as it is just the simple
overhead for invoking a method. Thus I think it might be interesting to
explore a multi-pixel method for ImageBuilder.
> TIFF reading extremely slow in version 1.0-SNAPSHOT
> ---------------------------------------------------
>
> Key: IMAGING-356
> URL: https://issues.apache.org/jira/browse/IMAGING-356
> Project: Commons Imaging
> Issue Type: Bug
> Components: Format: TIFF
> Affects Versions: 1.0
> Reporter: Gary Lucas
> Priority: Major
> Attachments: image-2023-07-04-08-52-36-535.png
>
>
> I am using the latest code from github (1.0-SNAPSHOT downloaded from github
> of June 2023) to read a 300 megabyte TIFF file. Version 1.0-alpha3 required
> 673 milliseconds to read that file. The new code requires upward of 15
> minutes. Clearly something got broken since the last release.
> The TIFF file is a 10000x10000 pixel 4 byte image format organized in strips.
> The bottleneck appears to occur in the TiffReader getTiffRawImageData method
> which reads raw data from the file in preparation of creating a BufferedImage
> object.
> I suspect that there may be a general slowness of file access. In debugging,
> even reading the initial metadata (22 TIFF tags) took a couple of seconds.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)