Author: jukka
Date: Tue Dec 17 19:58:24 2013
New Revision: 1551674

URL: http://svn.apache.org/r1551674
Log:
OAK-1273: Reduce overhead when handling many parallel property indices

Optimize MapRecord.getEntry() lookup heuristics

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

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MapRecord.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MapRecord.java?rev=1551674&r1=1551673&r2=1551674&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MapRecord.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MapRecord.java
 Tue Dec 17 19:58:24 2013
@@ -17,7 +17,6 @@
 package org.apache.jackrabbit.oak.plugins.segment;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.collect.Iterables.concat;
 import static com.google.common.collect.Lists.newArrayListWithCapacity;
 import static java.lang.Integer.bitCount;
@@ -172,28 +171,35 @@ class MapRecord extends Record {
             }
         }
 
-        // this is a leaf record; scan the list to find a matching entry
+        // use interpolation search to find the matching entry in this map leaf
+        int shift = 32 - level * BITS_PER_LEVEL;
+        long mask = -1L << shift;
         long h = hash & HASH_MASK;
         int p = 0;
-        long pH = 0;
+        long pH = h & mask;   // lower bound on hash values in this map leaf
         int q = size - 1;
-        long qH = HASH_MASK;
+        long qH = pH | ~mask; // upper bound on hash values in this map leaf
         while (p <= q) {
-            checkState(pH <= qH);
+            assert pH <= qH;
+
+            // interpolate the most likely index of the target entry
+            // based on its hash code and the lower and upper bounds
             int i = p + (int) ((q - p) * (h - pH) / (qH - pH));
-            checkState(p <= i && i <= q);
+            assert p <= i && i <= q;
+
             long iH = segment.readInt(getOffset(4 + i * 4)) & HASH_MASK;
             int diff = Long.valueOf(iH).compareTo(Long.valueOf(h));
             if (diff == 0) {
                 RecordId keyId = segment.readRecordId(
                         getOffset(4 + size * 4, i * 2));
+                RecordId valueId = segment.readRecordId(
+                        getOffset(4 + size * 4, i * 2 + 1));
                 diff = segment.readString(keyId).compareTo(name);
                 if (diff == 0) {
-                    RecordId valueId = segment.readRecordId(
-                            getOffset(4 + size * 4, i * 2 + 1));
                     return new MapEntry(segment, name, keyId, valueId);
                 }
             }
+
             if (diff < 0) {
                 p = i + 1;
                 pH = iH;


Reply via email to