You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2022/06/29 17:15:31 UTC
[sis] branch geoapi-4.0 updated: Adjust the size of the temporary buffer for TIFF decompression.
This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git
The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
new 748a5a1fff Adjust the size of the temporary buffer for TIFF decompression.
748a5a1fff is described below
commit 748a5a1fff56952bdb47b7bc6a0c81385bc27376
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Wed Jun 29 19:15:08 2022 +0200
Adjust the size of the temporary buffer for TIFF decompression.
---
.../main/java/org/apache/sis/image/DataType.java | 14 ++++++++++-
.../java/org/apache/sis/image/package-info.java | 2 +-
.../storage/inflater/CompressionChannel.java | 28 +++++++++++++++++-----
.../sis/internal/storage/inflater/Inflater.java | 5 ++--
4 files changed, 39 insertions(+), 10 deletions(-)
diff --git a/core/sis-feature/src/main/java/org/apache/sis/image/DataType.java b/core/sis-feature/src/main/java/org/apache/sis/image/DataType.java
index 9c18299b04..56239f37dc 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/image/DataType.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/image/DataType.java
@@ -34,7 +34,7 @@ import static org.apache.sis.internal.util.Numerics.MAX_INTEGER_CONVERTIBLE_TO_F
* This is a type-safe version of the {@code TYPE_*} constants defined in {@link DataBuffer}.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 1.3
* @since 1.1
* @module
*/
@@ -257,6 +257,18 @@ public enum DataType {
return DataBuffer.getDataTypeSize(ordinal());
}
+ /**
+ * Returns the size in bytes of this data type.
+ * If the {@linkplain #size() number of bits} is smaller than {@value Byte#SIZE}, then this method returns 1.
+ *
+ * @return size in bytes of this data type, not smaller than 1.
+ *
+ * @since 1.3
+ */
+ public final int bytes() {
+ return Math.max(size() >>> 3, 1);
+ }
+
/**
* Returns whether this type is an unsigned integer type.
* Unsigned types are {@link #BYTE} and {@link #USHORT}.
diff --git a/core/sis-feature/src/main/java/org/apache/sis/image/package-info.java b/core/sis-feature/src/main/java/org/apache/sis/image/package-info.java
index 0862082562..234e989c43 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/image/package-info.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/image/package-info.java
@@ -42,7 +42,7 @@
* @author Rémi Maréchal (Geomatys)
* @author Martin Desruisseaux (Geomatys)
* @author Johann Sorel (Geomatys)
- * @version 1.2
+ * @version 1.3
* @since 1.0
* @module
*/
diff --git a/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/CompressionChannel.java b/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/CompressionChannel.java
index 95e5473fb2..f80239ab1c 100644
--- a/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/CompressionChannel.java
+++ b/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/CompressionChannel.java
@@ -16,8 +16,11 @@
*/
package org.apache.sis.internal.storage.inflater;
+import java.util.Arrays;
import java.io.IOException;
import java.nio.ByteBuffer;
+import org.apache.sis.math.MathFunctions;
+import org.apache.sis.internal.util.Numerics;
import org.apache.sis.internal.geotiff.Resources;
import org.apache.sis.internal.storage.io.ChannelDataInput;
@@ -29,15 +32,16 @@ import org.apache.sis.internal.storage.io.ChannelDataInput;
* <p>The {@link #close()} method shall be invoked when this channel is no longer used.</p>
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 1.3
* @since 1.1
* @module
*/
abstract class CompressionChannel extends PixelChannel {
/**
- * Size of the buffer where to temporarily copy decompressed data.
+ * Desired size of the buffer where to temporarily copy decompressed data.
+ * The actual buffer size may be larger, but should not be smaller.
*/
- private static final int BUFFER_SIZE = 4096;
+ private static final int BUFFER_SIZE = 8192;
/**
* The source of data to decompress.
@@ -86,13 +90,25 @@ abstract class CompressionChannel extends PixelChannel {
* Creates the data input stream to use for getting uncompressed data.
* The {@linkplain #input} stream must be on the start position before to invoke this method.
*
- * @param channel the channel to wrap. This is {@code this} unless a {@link Predictor} is applied.
+ * <p>This method tries to create a buffer of the size of scanline stride, or a multiple of that size,
+ * for performance reasons. A well adjusted buffer size reduces calls to {@link ByteBuffer#compact()},
+ * which in turn reduces the amount of copy operations between different regions of the buffer.</p>
+ *
+ * @param channel the channel to wrap. This is {@code this} unless a {@link Predictor} is applied.
+ * @param scanlineStride the scanline stride of the image to read. Used for choosing a buffer size.
* @throws IOException if an error occurred while filling the buffer with initial data.
* @return the data input for uncompressed data.
*/
- final ChannelDataInput createDataInput(final PixelChannel channel) throws IOException {
+ final ChannelDataInput createDataInput(final PixelChannel channel, int scanlineStride) throws IOException {
+ if (scanlineStride > BUFFER_SIZE) {
+ final int[] divisors = MathFunctions.divisors(scanlineStride);
+ int i = Arrays.binarySearch(divisors, BUFFER_SIZE);
+ if (i < 0) i = ~i; // Really tild, not minus.
+ scanlineStride = divisors[i];
+ }
+ final int capacity = Numerics.ceilDiv(BUFFER_SIZE, scanlineStride) * scanlineStride;
// TODO: remove cast with JDK9.
- final ByteBuffer buffer = (ByteBuffer) ByteBuffer.allocate(BUFFER_SIZE).order(input.buffer.order()).limit(0);
+ final ByteBuffer buffer = (ByteBuffer) ByteBuffer.allocate(capacity).order(input.buffer.order()).limit(0);
return new ChannelDataInput(input.filename, channel, buffer, true);
}
diff --git a/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/Inflater.java b/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/Inflater.java
index 7321c5ed6e..cb6137895b 100644
--- a/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/Inflater.java
+++ b/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/Inflater.java
@@ -239,8 +239,9 @@ public abstract class Inflater implements Closeable {
throw unsupportedEncoding(caller, Resources.Keys.UnsupportedPredictor_1, predictor);
}
}
- return CopyFromBytes.create(inflater.createDataInput(channel), dataType,
- chunksPerRow, samplesPerChunk, skipAfterChunks, pixelsPerElement);
+ final int scanlineStride = Math.multiplyExact(sourceWidth, sourcePixelStride * dataType.bytes());
+ return CopyFromBytes.create(inflater.createDataInput(channel, scanlineStride),
+ dataType, chunksPerRow, samplesPerChunk, skipAfterChunks, pixelsPerElement);
}
/**