Optimize FileChannelJournalSegmentReader channel use 62/110562/2
authorRobert Varga <robert.varga@pantheon.tech>
Sat, 9 Mar 2024 09:47:49 +0000 (10:47 +0100)
committerRobert Varga <nite@hq.sk>
Mon, 11 Mar 2024 12:51:11 +0000 (12:51 +0000)
We use FileChannel to maintain our position for a particular reader,
which is a naive implementation.

Since FileChannel's position is tied to the underlying file descriptor,
each such manipulation involves locking and system calls.

Switch to maintaining the position ourselves and using
FileChannel.read(buffer, position), improving performance.

JIRA: CONTROLLER-2094
Change-Id: I7f462f3fd8aa9bc47c16201dd32faeb2a7c18a32
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
atomix-storage/src/main/java/io/atomix/storage/journal/FileChannelJournalSegmentReader.java

index 696ab45cdeb06cb7e895941cc8bbb94b61d902c2..46d7a659568eb0e3b7703adc461cb1d1ed1c9d06 100644 (file)
@@ -39,6 +39,7 @@ final class FileChannelJournalSegmentReader<E> implements JournalReader<E> {
   private final long firstIndex;
   private Indexed<E> currentEntry;
   private Indexed<E> nextEntry;
+  private long currentPosition;
 
   FileChannelJournalSegmentReader(
       FileChannel channel,
@@ -81,12 +82,8 @@ final class FileChannelJournalSegmentReader<E> implements JournalReader<E> {
     Position position = this.index.lookup(index - 1);
     if (position != null) {
       currentEntry = new Indexed<>(position.index() - 1, null, 0);
-      try {
-        channel.position(position.position());
-        memory.clear().flip();
-      } catch (IOException e) {
-        throw new StorageException(e);
-      }
+      currentPosition = position.position();
+      memory.clear().flip();
       readNext();
     }
     while (getNextIndex() < index && hasNext()) {
@@ -96,11 +93,7 @@ final class FileChannelJournalSegmentReader<E> implements JournalReader<E> {
 
   @Override
   public void reset() {
-    try {
-      channel.position(JournalSegmentDescriptor.BYTES);
-    } catch (IOException e) {
-      throw new StorageException(e);
-    }
+    currentPosition = JournalSegmentDescriptor.BYTES;
     memory.clear().limit(0);
     currentEntry = null;
     nextEntry = null;
@@ -145,11 +138,10 @@ final class FileChannelJournalSegmentReader<E> implements JournalReader<E> {
     try {
       // Read more bytes from the segment if necessary.
       if (memory.remaining() < maxEntrySize) {
-        long position = channel.position() + memory.position();
-        channel.position(position);
+        long position = currentPosition + memory.position();
         memory.clear();
-        channel.read(memory);
-        channel.position(position);
+        channel.read(memory, position);
+        currentPosition = position;
         memory.flip();
       }