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:19:46 UTC
svn commit: r1583880 - 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:19:45 2014
New Revision: 1583880
URL: http://svn.apache.org/r1583880
Log:
OAK-1660 - SegmentMK: Optimize reading of large binaries
Merge adjacent block records into one big block when reading
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=1583880&r1=1583879&r2=1583880&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:19:45 2014
@@ -50,7 +50,6 @@ class ListRecord extends Record {
public RecordId getEntry(int index) {
checkElementIndex(index, size);
-
if (size == 1) {
return getRecordId();
} else {
@@ -65,24 +64,30 @@ class ListRecord extends Record {
}
public List<RecordId> getEntries() {
- if (size == 0) {
+ return getEntries(0, size);
+ }
+
+ public List<RecordId> getEntries(int index, int count) {
+ if (index + count > size) {
+ count = size - index;
+ }
+ if (size == 0 || count == 0) {
return emptyList();
} else if (size == 1) {
return singletonList(getRecordId());
} else {
- List<RecordId> list = newArrayListWithCapacity(size);
+ List<RecordId> list = newArrayListWithCapacity(count);
Segment segment = getSegment();
- int offset = getOffset();
- for (int i = 0; i < size; i += bucketSize) {
- RecordId id = segment.readRecordId(offset);
- if (bucketSize == 1) {
- list.add(id);
- } else {
- ListRecord bucket = new ListRecord(
- id, Math.min(bucketSize, size - i));
- list.addAll(bucket.getEntries());
- }
- offset += Segment.RECORD_ID_BYTES;
+ while (count > 0) {
+ int bucketIndex = index / bucketSize;
+ int bucketOffset = index % bucketSize;
+ RecordId id = segment.readRecordId(getOffset(0, bucketIndex));
+ 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));
+ 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=1583880&r1=1583879&r2=1583880&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:19:45 2014
@@ -19,10 +19,12 @@ 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 org.apache.jackrabbit.oak.plugins.segment.SegmentWriter.BLOCK_SIZE;
import java.io.IOException;
import java.io.InputStream;
+import java.util.List;
import javax.annotation.CheckForNull;
@@ -113,7 +115,7 @@ public class SegmentStream extends Input
@Override
public int read() {
byte[] b = new byte[1];
- if (read(b) != -1) {
+ if (read(b, 0, 1) != -1) {
return b[0] & 0xff;
} else {
return -1;
@@ -121,38 +123,51 @@ public class SegmentStream extends Input
}
@Override
- public int read(byte[] b) {
- return read(b, 0, b.length);
- }
-
- @Override
public int read(byte[] b, int off, int len) {
checkNotNull(b);
checkPositionIndexes(off, off + len, b.length);
+
if (len == 0) {
return 0;
} else if (position == length) {
return -1;
- } else if (inline != null) {
- if (position + len > length) {
- len = (int) (length - position);
- }
+ }
+
+ if (position + len > length) {
+ len = (int) (length - position); // > 0 given the earlier check
+ }
+
+ if (inline != null) {
System.arraycopy(inline, (int) position, b, off, len);
position += len;
return len;
} else {
- int blockIndex = (int) (position / SegmentWriter.BLOCK_SIZE);
- int blockOffset = (int) (position % SegmentWriter.BLOCK_SIZE);
-
- if (blockOffset + len > SegmentWriter.BLOCK_SIZE) {
- len = SegmentWriter.BLOCK_SIZE - blockOffset;
+ 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
+ / BLOCK_SIZE;
+
+ 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) {
+ count++;
+ } else {
+ break;
+ }
}
- if (position + len > length) {
- len = (int) (length - position);
+
+ if (blockOffset + len > count * BLOCK_SIZE) {
+ len = count * BLOCK_SIZE - blockOffset;
}
- BlockRecord block =
- new BlockRecord(blocks.getEntry(blockIndex), BLOCK_SIZE);
+ BlockRecord block = new BlockRecord(first, blockOffset + len);
len = block.read(blockOffset, b, off, len);
position += len;
return len;