You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ju...@apache.org on 2014/04/02 07:20:20 UTC

svn commit: r1583881 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment: ListRecord.java SegmentStream.java

Author: jukka
Date: Wed Apr  2 05:20:20 2014
New Revision: 1583881

URL: http://svn.apache.org/r1583881
Log:
OAK-1660 - SegmentMK: Optimize reading of large binaries

Some further improvements

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/ListRecord.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentStream.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/ListRecord.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/ListRecord.java?rev=1583881&r1=1583880&r2=1583881&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/ListRecord.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/ListRecord.java Wed Apr  2 05:20:20 2014
@@ -18,6 +18,7 @@ package org.apache.jackrabbit.oak.plugin
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkElementIndex;
+import static com.google.common.base.Preconditions.checkPositionIndexes;
 import static com.google.common.collect.Lists.newArrayListWithCapacity;
 import static java.util.Collections.emptyList;
 import static java.util.Collections.singletonList;
@@ -71,13 +72,27 @@ class ListRecord extends Record {
         if (index + count > size) {
             count = size - index;
         }
-        if (size == 0 || count == 0) {
+        if (count == 0) {
             return emptyList();
-        } else if (size == 1) {
-            return singletonList(getRecordId());
+        } else if (count == 1) {
+            return singletonList(getEntry(index));
+        } else {
+            List<RecordId> ids = newArrayListWithCapacity(count);
+            getEntries(index, count, ids);
+            return ids;
+        }
+    }
+
+    private void getEntries(int index, int count, List<RecordId> ids) {
+        checkPositionIndexes(index, index + count, size);
+        Segment segment = getSegment();
+        if (size == 1) {
+            ids.add(getRecordId());
+        } else if (bucketSize == 1) {
+            for (int i = 0; i < count; i++) {
+                ids.add(segment.readRecordId(getOffset(0, index + i)));
+            }
         } else {
-            List<RecordId> list = newArrayListWithCapacity(count);
-            Segment segment = getSegment();
             while (count > 0) {
                 int bucketIndex = index / bucketSize;
                 int bucketOffset = index % bucketSize;
@@ -85,11 +100,10 @@ class ListRecord extends Record {
                 ListRecord bucket = new ListRecord(
                         id, Math.min(bucketSize, size - bucketIndex * bucketSize));
                 int n = Math.min(bucket.size() - bucketOffset, count);
-                list.addAll(bucket.getEntries(bucketOffset, n));
+                bucket.getEntries(bucketOffset, n, ids);
                 index += n;
                 count -= n;
             }
-            return list;
         }
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentStream.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentStream.java?rev=1583881&r1=1583880&r2=1583881&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentStream.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentStream.java Wed Apr  2 05:20:20 2014
@@ -19,7 +19,7 @@ package org.apache.jackrabbit.oak.plugin
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkPositionIndexes;
-import static org.apache.jackrabbit.oak.plugins.segment.Segment.MAX_SEGMENT_SIZE;
+import static com.google.common.base.Preconditions.checkState;
 import static org.apache.jackrabbit.oak.plugins.segment.SegmentWriter.BLOCK_SIZE;
 
 import java.io.IOException;
@@ -139,39 +139,46 @@ public class SegmentStream extends Input
 
         if (inline != null) {
             System.arraycopy(inline, (int) position, b, off, len);
-            position += len;
-            return len;
         } else {
             int blockIndex = (int) (position / BLOCK_SIZE);
             int blockOffset = (int) (position % BLOCK_SIZE);
             int blockCount =
-                    Math.min(MAX_SEGMENT_SIZE, blockOffset + len + BLOCK_SIZE - 1) // round up
+                    (blockOffset + len + BLOCK_SIZE - 1) // round up
                     / BLOCK_SIZE;
 
+            int remaining = len;
             List<RecordId> ids = blocks.getEntries(blockIndex, blockCount);
             RecordId first = ids.get(0); // guaranteed to contain at least one
-            SegmentId segmentId = first.getSegmentId();
-            int offset = first.getOffset();
             int count = 1;
-            while (count < ids.size()) {
-                RecordId id = ids.get(count);
-                if (id.getSegmentId() == segmentId
-                        && id.getOffset() == offset + count * BLOCK_SIZE) {
+            for (int i = 1; i <= ids.size(); i++) {
+                RecordId id = null;
+                if (i < ids.size()) {
+                    id = ids.get(i);
+                }
+
+                if (id != null
+                        && id.getSegmentId() == first.getSegmentId()
+                        && id.getOffset() == first.getOffset() + count * BLOCK_SIZE) {
                     count++;
                 } else {
-                    break;
+                    int blockSize = Math.min(
+                            blockOffset + remaining, count * BLOCK_SIZE);
+                    BlockRecord block = new BlockRecord(first, blockSize);
+                    int n = blockSize - blockOffset;
+                    checkState(block.read(blockOffset, b, off, n) == n);
+                    off += n;
+                    remaining -= n;
+
+                    first = id;
+                    count = 1;
+                    blockOffset = 0;
                 }
             }
-
-            if (blockOffset + len > count * BLOCK_SIZE) {
-                len = count * BLOCK_SIZE - blockOffset;
-            }
-
-            BlockRecord block = new BlockRecord(first, blockOffset + len);
-            len = block.read(blockOffset, b, off, len);
-            position += len;
-            return len;
+            checkState(remaining == 0);
         }
+
+        position += len;
+        return len;
     }
 
     @Override