-
Notifications
You must be signed in to change notification settings - Fork 109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Java2dProcessor performance on tiled pyramidal (jpeg) TIFFs #296
Comments
Hi @jbarth-ubhd, Can you share the TIFF file you are using? |
generated with Link to our presentation: Piranesi1770 Trofeo... Tafel_24 I've chosen 64×64px wide tiles because
|
Thanks, I've got it and will try to take a look soon. |
We see the same problem with pyramidal tiffs. Further analysis indicates, that this seems not directly related to the performance of scaling. Using source JPG with TurboJpegProcessor gives the following output (bicubic scaling takes 273ms, overall processing <500ms):
Using a pyramidal TIFF (converted from the jpeg) results in this (bicubic scaling takes >500ms, overall processing >1s):
I then compared performance of the same pyramidal tiff to IIPImage Server (using bilinear "interpolated" scaling). Which results in overall processing of <500ms (Factor 2!) It seems that without JAI, cantaloupe can't handle pyramidal tiffs anymore in an efficient way. I'm using a dockerized image based on OpenJDK-11 and Hotspot. Any ideas on this? |
I looked into this briefly a long time ago and my recollection is that it had something to do with the way the GeoSolutions TIFF Image I/O plugin creates BufferedImages, which ties into the idiosyncrasies of java.awt.image.BufferedImage, in particular its "types" and their suitability for Graphics2D processing. Basically the plugin tries to produce a BufferedImage with a ColorModel and SampleModel that are faithful to the source TIFF, but in many/most cases, this results in an image of "custom" type which Graphics2D is not optimized or able to process, requiring costly internal conversion. JAI doesn't suffer from this problem because it uses a different processing engine. A solution might involve either forking the plugin or moving to a different TIFF reading technique, but both of these will require time that I don't have currently. |
Thanks @adolski for this very helpful insight! Now it makes sense to me that the scaling takes longer... I will have a look at it, but don't know if I have time for it either. I hope pyramidal tiffs can soon be replaced with HTJ2K now that Grok supports it fully (see https://github.com/GrokImageCompression/grok/releases - I wonder whether I can maybe just use Cantaloupe's OpenJPEG integration with grk_decompress?) |
Actually went ahead and tried the just released version 4.1 of Grok (custom compile, symlinked opj_compress, commented out the "quiet" flag in the OpenJpegProcessor.java in Cantaloupe). Looks very promising on first impression - however I only compared on JPG sources for the moment (lossy HT "grk_compress -q 40 -M 32 -i 001_1974_000_0831.jpg -o 001_1974_000_0831.jp2"). Similar performance to TurboJpeg when using region display, a bit slower when displaying the full image. Decoding speed seems to depend heavily on compression parameters. Even though it's writing out the intermediate bmp, it's still much faster than using pyramidal tiff (with scaling the problem described above). So maybe it's a longer-term option to integrate grok :-)
|
@kaij I'm not very familiar with Grok, but if it works, then great. Longer-term I would like to call directly into the OpenJPEG library rather than relying on |
Still the same problem (cantaloupe 4.1.5): We'll have an image, size 26315×19908 px, pyramidal tiff: root@serv7:/srv/assets/assets/orig2/0/605000/605909# tiffinfo 1392039ec03494ade4b39060c02d64ecd1761951|grep -i width
Image Width: 26315 Image Length: 19908
Tile Width: 96 Tile Length: 96
Image Width: 13157 Image Length: 9954
Tile Width: 96 Tile Length: 96
Image Width: 6578 Image Length: 4977
Tile Width: 96 Tile Length: 96
Image Width: 3289 Image Length: 2488
Tile Width: 96 Tile Length: 96
Image Width: 1644 Image Length: 1244
Tile Width: 96 Tile Length: 96
Image Width: 822 Image Length: 622
Tile Width: 96 Tile Length: 96
Image Width: 411 Image Length: 311
Tile Width: 96 Tile Length: 96
Image Width: 205 Image Length: 155
Tile Width: 96 Tile Length: 96
Image Width: 102 Image Length: 77
Tile Width: 96 Tile Length: 96
Image Width: 51 Image Length: 38
Tile Width: 96 Tile Length: 96 Contains 1/1 … 1/512 image size. Now the requests (abbreviated + reformatted) from Firefox (Mirador viewer) with timings and image size fraction:
Multiple seconds, even at 1/1.000000 zoom. PS: changed to "wait" timings. |
@jbarth-ubhd can you share how much memory you have allocated for Cantaloupe? What caching is in place? Running this via jetty or in Tomcat? Which Java? Also version 4.1.5 is bit behind so I would compare at least with 4.1.7 if you are not ready for 5.0 (new configuration options/settings needed). There can be many factors in place too, from a slow Filesystem to many other concurrent connections. I would love to test your source image with other processors in one our system to compare. I'm not sure why (really not) but we had some TIFF speed issues (but not pyramidal ones) with Mirador v/s Open Sea dragon. It may be related to the tile sizes requested but since I have not explanation yet this is more like a comment without background. |
# Ubuntu 18.04
/usr/lib/jvm/java-1.11.0-openjdk-amd64/bin/java -Dcantaloupe.config=/usr/local/diglit/iiif/cantaloupe/config/cantaloupe⸗
.properties -Xmx2g -jar /usr/local/cantaloupe/cantaloupe-4.1.8.war Caching should not be the problem because requested zoom level exists in pyramidal tiff. Jetty. 4.1.8: the same timings. Did enable "debug" logging:
But 1536 / 768 = 2 — should be in pyramidal tiff. |
What means this: PS: does this mean that returning the uri from DelegateProxy took 2844 msec? |
Pyramidal tiff (for test purposes) is here: https://digi.ub.uni-heidelberg.de/diglitData/v/Rubens-tile94-deflate.tif |
Oops... our delegate needs indeed multiple seconds. |
besides the very slow response times of my PS: checked caching setting with PS2: why is caching removed from configuration in cantaloupe 5? |
@jbarth-ubhd The delegate method invocation cache was added some time ago when the delegate methods relied on arguments instead of the context. Adding the context broke it and it has probably been broken throughout the 4.1 series. This was just something that fell off my radar. In 5.0, the added richness of the context makes computing reliable cache keys difficult. I decided that I didn't want to support this feature anymore so I pulled it. If you need to employ caching, I recommend implementing your own cache. |
Did implement some primitive caching, now timings are much better:
|
Cantaloupe still scales from 1536 to 768 (÷2), which is in pyramidal tiff(?) But the requested size was 3072×3072... what has 1536 to do with this?
|
@jbarth-ubhd The dimensions of the individual pyramid levels should be logged in there somewhere, if you can set |
PS: instead of own cache implementation I'll use this tomorrow: require 'lru_redux'
$cache=LruRedux::TTL::ThreadSafeCache.new(maxItems, maxTTL)
print $cache.getset('kkkey'){
sleep 1 # something complicated
1 # return value
} |
@adolski: we'll change tile size from 96 to 256. Let's see … |
How do I add additional ruby libraries? Installed lru_redux with Gemfile + Tried |
It seems that the slower requests come from from requests, where the "tile" of the requested region is not a integer number (
|
Let's take the last request on the list above:
Why does cantaloupe scale? The image in the second tiff directory has the wanted scale, and the request perfectly matches the 256×256 tiles in this image. |
I'll open the last question in a new case. |
Dear reader, we have a tiled, pyramidal internally jpeg compressed tif of 9557×36619 px size.
When requesting region of x=2671 y=15179 w=6170 h=3471 at pct:31, cantaloupe is correctly getting the 50%-size image within the tiff, getting a 3085×1735 size image which has now to be scaled (bicubic) to 1913×1076px to match the »pct:31« above.
This takes 2.5 seconds according to log on an Intel Core i7-4790 CPU @ 3.60GHz.
Imagemagick requires about 0.1 s for this (Q16, no hdri), and this snippet in java does take 0.21 s for downsampling:
What could be done to speed up Java2dProcessor?
ImageMagickProcessor takes about 97 s, because identify reads in the whole image,
GraphicsMagickProcessor takes about 4 s...
and JaiProcessor does use NearestNeighbour because of a Jai bug...
Kind regards,
Jochen
The text was updated successfully, but these errors were encountered: