Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Licensed to the Apache Software Foundation (ASF) under one or more
0003  * contributor license agreements.  See the NOTICE file distributed with
0004  * this work for additional information regarding copyright ownership.
0005  * The ASF licenses this file to You under the Apache License, Version 2.0
0006  * (the "License"); you may not use this file except in compliance with
0007  * the License.  You may obtain a copy of the License at
0008  *
0009  *    http://www.apache.org/licenses/LICENSE-2.0
0010  *
0011  * Unless required by applicable law or agreed to in writing, software
0012  * distributed under the License is distributed on an "AS IS" BASIS,
0013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014  * See the License for the specific language governing permissions and
0015  * limitations under the License.
0016  */
0017 
0018 package org.apache.spark.sql.execution;
0019 
0020 import org.apache.spark.unsafe.Platform;
0021 import org.apache.spark.util.collection.unsafe.sort.RecordComparator;
0022 
0023 import java.nio.ByteOrder;
0024 
0025 public final class RecordBinaryComparator extends RecordComparator {
0026 
0027   private static final boolean LITTLE_ENDIAN =
0028       ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN);
0029 
0030   @Override
0031   public int compare(
0032       Object leftObj, long leftOff, int leftLen, Object rightObj, long rightOff, int rightLen) {
0033     int i = 0;
0034 
0035     // If the arrays have different length, the longer one is larger.
0036     if (leftLen != rightLen) {
0037       return leftLen - rightLen;
0038     }
0039 
0040     // The following logic uses `leftLen` as the length for both `leftObj` and `rightObj`, since
0041     // we have guaranteed `leftLen` == `rightLen`.
0042 
0043     // check if stars align and we can get both offsets to be aligned
0044     if ((leftOff % 8) == (rightOff % 8)) {
0045       while ((leftOff + i) % 8 != 0 && i < leftLen) {
0046         final int v1 = Platform.getByte(leftObj, leftOff + i);
0047         final int v2 = Platform.getByte(rightObj, rightOff + i);
0048         if (v1 != v2) {
0049           return (v1 & 0xff) > (v2 & 0xff) ? 1 : -1;
0050         }
0051         i += 1;
0052       }
0053     }
0054     // for architectures that support unaligned accesses, chew it up 8 bytes at a time
0055     if (Platform.unaligned() || (((leftOff + i) % 8 == 0) && ((rightOff + i) % 8 == 0))) {
0056       while (i <= leftLen - 8) {
0057         long v1 = Platform.getLong(leftObj, leftOff + i);
0058         long v2 = Platform.getLong(rightObj, rightOff + i);
0059         if (v1 != v2) {
0060           if (LITTLE_ENDIAN) {
0061             // if read as little-endian, we have to reverse bytes so that the long comparison result
0062             // is equivalent to byte-by-byte comparison result.
0063             // See discussion in https://github.com/apache/spark/pull/26548#issuecomment-554645859
0064             v1 = Long.reverseBytes(v1);
0065             v2 = Long.reverseBytes(v2);
0066           }
0067           return Long.compareUnsigned(v1, v2);
0068         }
0069         i += 8;
0070       }
0071     }
0072     // this will finish off the unaligned comparisons, or do the entire aligned comparison
0073     // whichever is needed.
0074     while (i < leftLen) {
0075       final int v1 = Platform.getByte(leftObj, leftOff + i);
0076       final int v2 = Platform.getByte(rightObj, rightOff + i);
0077       if (v1 != v2) {
0078         return (v1 & 0xff) > (v2 & 0xff) ? 1 : -1;
0079       }
0080       i += 1;
0081     }
0082 
0083     // The two arrays are equal.
0084     return 0;
0085   }
0086 }