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 2021/10/29 22:43:24 UTC

[sis] 01/02: Avoid seek operations on very short distances (less than 8 bytes).

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

commit 32175f205fce083591e6f8976965561ffe464fa8
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Sat Oct 30 00:39:37 2021 +0200

    Avoid seek operations on very short distances (less than 8 bytes).
---
 .../apache/sis/internal/storage/io/ChannelDataInput.java  | 15 +++++++++++++--
 .../sis/internal/storage/io/ChannelDataInputTest.java     |  7 ++++---
 .../sis/internal/storage/io/ChannelDataOutputTest.java    |  6 +++---
 .../sis/internal/storage/io/ChannelDataTestCase.java      | 15 ++++++++++++++-
 .../internal/storage/io/ChannelImageOutputStreamTest.java |  4 ++--
 5 files changed, 36 insertions(+), 11 deletions(-)

diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java
index 3cd04e1..5f562b7 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java
@@ -61,12 +61,23 @@ import static org.apache.sis.util.ArgumentChecks.ensureBetween;
  * {@link javax.imageio} is needed.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.2
  * @since   0.3
  * @module
  */
 public class ChannelDataInput extends ChannelData {
     /**
+     * Minimum number of bytes to skip in the {@code seek(long)} operation.
+     * If there is less bytes to skip, then it is not worth to do a seek
+     * and we will continue reading as normal instead.
+     *
+     * <p>This threshold is used because some formats add padding to their data for aligning on 32 bits boundary.
+     * It may result in very small seeks before reading the next chunk of data. A common padding is 32 bits,
+     * but there is no harm in using a larger one here (64 bits).</p>
+     */
+    private static final int SEEK_THRESHOLD = Long.BYTES;
+
+    /**
      * The channel from where data are read.
      * This is supplied at construction time.
      */
@@ -864,7 +875,7 @@ public class ChannelDataInput extends ChannelData {
              * Requested position is inside the current limits of the buffer.
              */
             buffer.position((int) p);
-        } else if (channel instanceof SeekableByteChannel) {
+        } else if ((p < 0 || p - buffer.limit() >= SEEK_THRESHOLD) && channel instanceof SeekableByteChannel) {
             /*
              * Requested position is outside the current limits of the buffer,
              * but we can set the new position directly in the channel. Note
diff --git a/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/ChannelDataInputTest.java b/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/ChannelDataInputTest.java
index 97e23fc..cbf4a8a 100644
--- a/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/ChannelDataInputTest.java
+++ b/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/ChannelDataInputTest.java
@@ -32,7 +32,7 @@ import static org.junit.Assert.*;
  * of that buffer is used for the tests, while the original full buffer is used for comparison purpose.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.5
+ * @version 1.2
  * @since   0.3
  * @module
  */
@@ -58,8 +58,9 @@ public final strictfp class ChannelDataInputTest extends ChannelDataTestCase {
     public void testAllReadMethods() throws IOException {
         final byte[] array = createRandomArray(STREAM_LENGTH);
         referenceStream = new DataInputStream(new ByteArrayInputStream(array));
-        testedStream = new ChannelDataInput("testAllReadMethods", new DripByteChannel(array, random, 1, 1024),
-                ByteBuffer.allocate(random.nextInt(BUFFER_MAX_CAPACITY) + Double.BYTES), false);
+        testedStream = new ChannelDataInput("testAllReadMethods",
+                new DripByteChannel(array, random, 1, 1024),
+                ByteBuffer.allocate(randomBufferCapacity()), false);
         transferRandomData(testedStream, array.length - ARRAY_MAX_LENGTH, 16);
     }
 
diff --git a/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/ChannelDataOutputTest.java b/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/ChannelDataOutputTest.java
index 8366c64..cfacc0b 100644
--- a/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/ChannelDataOutputTest.java
+++ b/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/ChannelDataOutputTest.java
@@ -38,7 +38,7 @@ import static org.junit.Assert.*;
  *
  * @author  Rémi Maréchal (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.5
+ * @version 1.2
  * @since   0.5
  * @module
  */
@@ -108,7 +108,7 @@ public strictfp class ChannelDataOutputTest extends ChannelDataTestCase {
      */
     @Test
     public void testAllWriteMethods() throws IOException {
-        initialize("testAllWriteMethods", STREAM_LENGTH, random.nextInt(BUFFER_MAX_CAPACITY) + Double.BYTES);
+        initialize("testAllWriteMethods", STREAM_LENGTH, randomBufferCapacity());
         writeInStreams();
         assertStreamContentEquals();
     }
@@ -132,7 +132,7 @@ public strictfp class ChannelDataOutputTest extends ChannelDataTestCase {
     @Test
     @DependsOnMethod("testAllWriteMethods")
     public void testWriteAndSeek() throws IOException {
-        initialize("testWriteAndSeek", STREAM_LENGTH, random.nextInt(BUFFER_MAX_CAPACITY) + Double.BYTES);
+        initialize("testWriteAndSeek", STREAM_LENGTH, randomBufferCapacity());
         writeInStreams();
         ((Closeable) referenceStream).close();
         final byte[] expectedArray = expectedData.toByteArray();
diff --git a/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/ChannelDataTestCase.java b/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/ChannelDataTestCase.java
index 7c7575f..3d5705f 100644
--- a/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/ChannelDataTestCase.java
+++ b/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/ChannelDataTestCase.java
@@ -29,7 +29,7 @@ import org.apache.sis.util.Debug;
  *
  * @author  Rémi Maréchal (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.5
+ * @version 1.2
  * @since   0.5
  * @module
  */
@@ -43,6 +43,11 @@ abstract strictfp class ChannelDataTestCase extends TestCase {
     static final int ARRAY_MAX_LENGTH = 256;
 
     /**
+     * The minimal capacity of the buffer to use for write operations.
+     */
+    static final int BUFFER_MIN_CAPACITY = Double.BYTES;
+
+    /**
      * The maximal capacity of the buffer to use for write operations.
      */
     static final int BUFFER_MAX_CAPACITY = ARRAY_MAX_LENGTH / 4;
@@ -82,6 +87,14 @@ abstract strictfp class ChannelDataTestCase extends TestCase {
     }
 
     /**
+     * Returns a random buffer capacity between {@value #BUFFER_MIN_CAPACITY}
+     * and {@value #BUFFER_MAX_CAPACITY} inclusive.
+     */
+    final int randomBufferCapacity() {
+        return random.nextInt(BUFFER_MAX_CAPACITY - BUFFER_MIN_CAPACITY + 1) + BUFFER_MIN_CAPACITY;
+    }
+
+    /**
      * Transfers many random data between the channel and the buffer.
      * This method invokes {@link #transferRandomData(int)} in a loop,
      * with an operation identifier selected randomly between 0 inclusive to {@code numOperations} exclusive.
diff --git a/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/ChannelImageOutputStreamTest.java b/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/ChannelImageOutputStreamTest.java
index cb76884..a78e3d4 100644
--- a/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/ChannelImageOutputStreamTest.java
+++ b/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/ChannelImageOutputStreamTest.java
@@ -33,7 +33,7 @@ import static org.junit.Assert.*;
  *
  * @author  Rémi Maréchal (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.5
+ * @version 1.2
  * @since   0.5
  * @module
  */
@@ -58,7 +58,7 @@ public final strictfp class ChannelImageOutputStreamTest extends ChannelDataOutp
      */
     @Test
     public void testWriteBits() throws IOException {
-        initialize("testWriteBits", STREAM_LENGTH, random.nextInt(BUFFER_MAX_CAPACITY) + Long.BYTES);
+        initialize("testWriteBits", STREAM_LENGTH, randomBufferCapacity());
         final ImageOutputStream referenceStream = (ImageOutputStream) this.referenceStream;
         final int length = testedStreamBackingArray.length - ARRAY_MAX_LENGTH; // Keep a margin against buffer underflow.
         while (testedStream.getStreamPosition() < length) {