Author: alexparvulescu Date: Fri Apr 7 11:49:52 2017 New Revision: 1790536
URL: http://svn.apache.org/viewvc?rev=1790536&view=rev Log: OAK-5910 Reduce copying of data when reading mmapped records Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordId.java jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBlob.java jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeState.java jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentStream.java jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentWriter.java jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/NodeRecordTest.java Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordId.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordId.java?rev=1790536&r1=1790535&r2=1790536&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordId.java (original) +++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordId.java Fri Apr 7 11:49:52 2017 @@ -22,6 +22,7 @@ import static com.google.common.base.Pre import static java.lang.Integer.parseInt; import static org.apache.jackrabbit.oak.segment.CacheWeights.OBJECT_HEADER_SIZE; +import java.nio.ByteBuffer; import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -102,12 +103,12 @@ public final class RecordId implements C * @return this record id as byte array */ @Nonnull - byte[] getBytes() { + ByteBuffer getBytes() { byte[] buffer = new byte[SERIALIZED_RECORD_ID_BYTES]; BinaryUtils.writeLong(buffer, 0, segmentId.getMostSignificantBits()); BinaryUtils.writeLong(buffer, 8, segmentId.getLeastSignificantBits()); BinaryUtils.writeInt(buffer, 16, offset); - return buffer; + return ByteBuffer.wrap(buffer); } //--------------------------------------------------------< Comparable >-- Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java?rev=1790536&r1=1790535&r2=1790536&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java (original) +++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java Fri Apr 7 11:49:52 2017 @@ -441,27 +441,18 @@ public class Segment { return data.getLong(pos(recordNumber, 8)); } - /** - * Reads the given number of bytes starting from the given position - * in this segment. - * - * @param recordNumber position within segment - * @param buffer target buffer - * @param offset offset within target buffer - * @param length number of bytes to read - */ - void readBytes(int recordNumber, byte[] buffer, int offset, int length) { - readBytes(recordNumber, 0, buffer, offset, length); - } - void readBytes(int recordNumber, int position, byte[] buffer, int offset, int length) { checkNotNull(buffer); checkPositionIndexes(offset, offset + length, buffer.length); - ByteBuffer d = data.duplicate(); - d.position(pos(recordNumber, position, length)); + ByteBuffer d = readBytes(recordNumber, position, length); d.get(buffer, offset, length); } + ByteBuffer readBytes(int recordNumber, int position, int length) { + int pos = pos(recordNumber, position, length); + return slice(pos, length); + } + @Nonnull RecordId readRecordId(int recordNumber, int rawOffset, int recordIdOffset) { return internalReadRecordId(pos(recordNumber, rawOffset, recordIdOffset, RECORD_ID_BYTES)); @@ -505,17 +496,9 @@ public class Segment { int pos = pos(offset, 1); long length = internalReadLength(pos); if (length < SMALL_LIMIT) { - byte[] bytes = new byte[(int) length]; - ByteBuffer buffer = data.duplicate(); - buffer.position(pos + 1); - buffer.get(bytes); - return new String(bytes, Charsets.UTF_8); + return Charsets.UTF_8.decode(slice(pos + 1, (int) length)).toString(); } else if (length < MEDIUM_LIMIT) { - byte[] bytes = new byte[(int) length]; - ByteBuffer buffer = data.duplicate(); - buffer.position(pos + 2); - buffer.get(bytes); - return new String(bytes, Charsets.UTF_8); + return Charsets.UTF_8.decode(slice(pos + 2, (int) length)).toString(); } else if (length < Integer.MAX_VALUE) { int size = (int) ((length + BLOCK_SIZE - 1) / BLOCK_SIZE); ListRecord list = new ListRecord(internalReadRecordId(pos + 8), size); @@ -527,6 +510,13 @@ public class Segment { } } + private ByteBuffer slice(int pos, int length) { + ByteBuffer buffer = data.duplicate(); + buffer.position(pos); + buffer.limit(pos + length); + return buffer.slice(); + } + @Nonnull Template readTemplate(int recordNumber) { int head = readInt(recordNumber); Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBlob.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBlob.java?rev=1790536&r1=1790535&r2=1790536&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBlob.java (original) +++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBlob.java Fri Apr 7 11:49:52 2017 @@ -60,9 +60,7 @@ public class SegmentBlob extends Record } private InputStream getInlineStream(Segment segment, int offset, int length) { - byte[] inline = new byte[length]; - segment.readBytes(getRecordNumber(), offset, inline, 0, length); - return new SegmentStream(getRecordId(), inline); + return new SegmentStream(getRecordId(), segment.readBytes(getRecordNumber(), offset, length), length); } @Override @Nonnull @@ -202,9 +200,7 @@ public class SegmentBlob extends Record private static String readShortBlobId(Segment segment, int recordNumber, byte head) { int length = (head & 0x0f) << 8 | (segment.readByte(recordNumber, 1) & 0xff); - byte[] bytes = new byte[length]; - segment.readBytes(recordNumber, 2, bytes, 0, length); - return new String(bytes, UTF_8); + return UTF_8.decode(segment.readBytes(recordNumber, 2, length)).toString(); } private static String readLongBlobId(Segment segment, int recordNumber) { Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeState.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeState.java?rev=1790536&r1=1790535&r2=1790536&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeState.java (original) +++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeState.java Fri Apr 7 11:49:52 2017 @@ -117,7 +117,7 @@ public class SegmentNodeState extends Re * @return stable id */ String getStableId() { - ByteBuffer buffer = ByteBuffer.wrap(getStableIdBytes()); + ByteBuffer buffer = getStableIdBytes(); long msb = buffer.getLong(); long lsb = buffer.getLong(); int offset = buffer.getInt(); @@ -132,7 +132,7 @@ public class SegmentNodeState extends Re * * @return the stable ID of this node. */ - byte[] getStableIdBytes() { + ByteBuffer getStableIdBytes() { // The first record id of this node points to the stable id. RecordId id = getSegment().readRecordId(getRecordNumber()); @@ -144,9 +144,7 @@ public class SegmentNodeState extends Re } else { // Otherwise that id points to the serialised (msb, lsb, offset) // stable id. - byte[] buffer = new byte[RecordId.SERIALIZED_RECORD_ID_BYTES]; - id.getSegment().readBytes(id.getRecordNumber(), buffer, 0, buffer.length); - return buffer; + return id.getSegment().readBytes(id.getRecordNumber(), 0, RecordId.SERIALIZED_RECORD_ID_BYTES); } } Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentStream.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentStream.java?rev=1790536&r1=1790535&r2=1790536&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentStream.java (original) +++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentStream.java Fri Apr 7 11:49:52 2017 @@ -26,6 +26,7 @@ import static org.apache.jackrabbit.oak. import java.io.IOException; import java.io.InputStream; +import java.nio.ByteBuffer; import java.util.List; import javax.annotation.CheckForNull; @@ -72,11 +73,13 @@ public class SegmentStream extends Input this.length = length; } - SegmentStream(RecordId recordId, byte[] inline) { + SegmentStream(RecordId recordId, ByteBuffer inline, int length) { this.recordId = checkNotNull(recordId); - this.inline = checkNotNull(inline); + // TODO rewrite this class to leverage the ByteBuffer apis + this.inline = new byte[length]; + inline.get(this.inline); this.blocks = null; - this.length = inline.length; + this.length = length; } List<RecordId> getBlockIds() { Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentWriter.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentWriter.java?rev=1790536&r1=1790535&r2=1790536&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentWriter.java (original) +++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentWriter.java Fri Apr 7 11:49:52 2017 @@ -51,6 +51,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.SequenceInputStream; +import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -1026,7 +1027,9 @@ public class SegmentWriter { RecordId stableId = null; if (state instanceof SegmentNodeState) { - byte[] id = ((SegmentNodeState) state).getStableIdBytes(); + ByteBuffer bid = ((SegmentNodeState) state).getStableIdBytes(); + byte[] id = new byte[RecordId.SERIALIZED_RECORD_ID_BYTES]; + bid.get(id); stableId = writeBlock(id, 0, id.length); } return newNodeStateWriter(stableId, ids).write(writer, store); Modified: jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/NodeRecordTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/NodeRecordTest.java?rev=1790536&r1=1790535&r2=1790536&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/NodeRecordTest.java (original) +++ jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/NodeRecordTest.java Fri Apr 7 11:49:52 2017 @@ -22,6 +22,8 @@ import static org.junit.Assert.assertEqu import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; +import java.nio.ByteBuffer; + import javax.annotation.Nonnull; import com.google.common.base.Supplier; @@ -82,11 +84,17 @@ public class NodeRecordTest { SegmentNodeState three = writer.writeNode(two); writer.flush(); - assertArrayEquals(three.getStableIdBytes(), two.getStableIdBytes()); - assertArrayEquals(two.getStableIdBytes(), one.getStableIdBytes()); + assertArrayEquals(asByteArray(three.getStableIdBytes()), asByteArray(two.getStableIdBytes())); + assertArrayEquals(asByteArray(two.getStableIdBytes()), asByteArray(one.getStableIdBytes())); } } + private static final byte[] asByteArray(ByteBuffer bytes) { + byte[] buffer = new byte[RecordId.SERIALIZED_RECORD_ID_BYTES]; + bytes.get(buffer); + return buffer; + } + @Test public void baseNodeStateShouldBeReusedAcrossGenerations() throws Exception { try (FileStore store = newFileStore()) {
