Author: mduerig
Date: Wed Oct 19 08:37:12 2016
New Revision: 1765553

URL: http://svn.apache.org/viewvc?rev=1765553&view=rev
Log:
OAK-4923: Improve segment deserialization performance
Load (and cache) segment references lazyly

Removed:
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/ImmutableSegmentReferences.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/ImmutableSegmentReferencesTest.java
Modified:
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java

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=1765553&r1=1765552&r2=1765553&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
 Wed Oct 19 08:37:12 2016
@@ -18,10 +18,10 @@
  */
 package org.apache.jackrabbit.oak.segment;
 
+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 com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.Lists.newArrayListWithCapacity;
 import static com.google.common.collect.Maps.newLinkedHashMap;
 import static org.apache.jackrabbit.oak.commons.IOUtils.closeQuietly;
 import static org.apache.jackrabbit.oak.segment.SegmentId.isDataSegmentId;
@@ -37,7 +37,7 @@ import java.nio.ByteBuffer;
 import java.nio.channels.Channels;
 import java.nio.channels.WritableByteChannel;
 import java.util.Arrays;
-import java.util.List;
+import java.util.Iterator;
 import java.util.Map;
 import java.util.UUID;
 
@@ -45,6 +45,7 @@ import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 
 import com.google.common.base.Charsets;
+import com.google.common.collect.AbstractIterator;
 import org.apache.commons.io.HexDump;
 import org.apache.commons.io.output.ByteArrayOutputStream;
 import org.apache.jackrabbit.oak.api.PropertyState;
@@ -248,21 +249,44 @@ public class Segment {
         checkState(getReferencedSegmentIdCount() + 1 < 0xffff,
                 "Segment cannot have more than 0xffff references");
 
-        List<SegmentId> referencedSegments = 
newArrayListWithCapacity(getReferencedSegmentIdCount());
-
-        int position = data.position();
-
-        position += HEADER_SIZE;
-
-        for (int i = 0; i < getReferencedSegmentIdCount(); i++) {
-            long msb = data.getLong(position);
-            position += 8;
-            long lsb = data.getLong(position);
-            position += 8;
-            referencedSegments.add(store.newSegmentId(msb, lsb));
-        }
-
-        return new ImmutableSegmentReferences(referencedSegments);
+        final int referencedSegmentIdCount = getReferencedSegmentIdCount();
+        final int refOffset = data.position() + HEADER_SIZE;
+        final SegmentId[] refIds = new SegmentId[referencedSegmentIdCount];
+        return new SegmentReferences() {
+            @Override
+            public SegmentId getSegmentId(int reference) {
+                checkArgument(reference <= referencedSegmentIdCount);
+                SegmentId id = refIds[reference - 1];
+                if (id == null) {
+                    synchronized(refIds) {
+                        id = refIds[reference - 1];
+                        if (id == null) {
+                            int position = refOffset + (reference - 1) * 
SEGMENT_REFERENCE_SIZE;
+                            long msb = data.getLong(position);
+                            long lsb = data.getLong(position + 8);
+                            id = store.newSegmentId(msb, lsb);
+                            refIds[reference - 1] = id;
+                        }
+                    }
+                }
+                return id;
+            }
+
+            @Override
+            public Iterator<SegmentId> iterator() {
+                return new AbstractIterator<SegmentId>() {
+                    private int reference = 1;
+                    @Override
+                    protected SegmentId computeNext() {
+                        if (reference <= referencedSegmentIdCount) {
+                            return getSegmentId(reference++);
+                        } else {
+                            return endOfData();
+                        }
+                    }
+                };
+            }
+        };
     }
 
     Segment(@Nonnull SegmentStore store,


Reply via email to