// This method is a hotspot, logic from RocksDbKeyValueServices.parseCellAndTs // is duplicated and tuned for perf. @Override public int compare(Slice a, Slice b) { byte[] adata = a.data(); byte[] bdata = b.data(); byte[] rowSizeBytes = new byte[2]; rowSizeBytes[0] = adata[adata.length - 1]; rowSizeBytes[1] = adata[adata.length - 2]; int aRowSize = (int) EncodingUtils.decodeVarLong(rowSizeBytes); rowSizeBytes[0] = bdata[bdata.length - 1]; rowSizeBytes[1] = bdata[bdata.length - 2]; int bRowSize = (int) EncodingUtils.decodeVarLong(rowSizeBytes); int comp = UnsignedBytes.lexicographicalComparator() .compare(Arrays.copyOf(adata, aRowSize), Arrays.copyOf(bdata, bRowSize)); if (comp != 0) { return comp; } int aColEnd = adata.length - 8 - EncodingUtils.sizeOfVarLong(aRowSize); int bColEnd = bdata.length - 8 - EncodingUtils.sizeOfVarLong(bRowSize); comp = UnsignedBytes.lexicographicalComparator() .compare( Arrays.copyOfRange(adata, aRowSize, aColEnd), Arrays.copyOfRange(bdata, bRowSize, bColEnd)); if (comp != 0) { return comp; } long aTs = Longs.fromBytes( adata[aColEnd + 0], adata[aColEnd + 1], adata[aColEnd + 2], adata[aColEnd + 3], adata[aColEnd + 4], adata[aColEnd + 5], adata[aColEnd + 6], adata[aColEnd + 7]); long bTs = Longs.fromBytes( bdata[bColEnd + 0], bdata[bColEnd + 1], bdata[bColEnd + 2], bdata[bColEnd + 3], bdata[bColEnd + 4], bdata[bColEnd + 5], bdata[bColEnd + 6], bdata[bColEnd + 7]); // Note: Ordering is reversed, later timestamps come before eariler ones. return Long.compare(bTs, aTs); }
@Override public int compareTo(Employee o) { int diff = ComparisonChain.start() .compare(lastName, o.lastName, Ordering.from(String.CASE_INSENSITIVE_ORDER)) .compare(firstName, o.firstName, Ordering.from(String.CASE_INSENSITIVE_ORDER)) .compare(title, o.title, Ordering.from(String.CASE_INSENSITIVE_ORDER).nullsFirst()) .compare( titleCourtesy, o.titleCourtesy, Ordering.from(String.CASE_INSENSITIVE_ORDER).nullsFirst()) .compare(birthDate, o.birthDate, Ordering.natural().nullsFirst()) .compare(hireDate, o.hireDate, Ordering.natural().nullsFirst()) .compare(address, o.address, Ordering.from(String.CASE_INSENSITIVE_ORDER).nullsFirst()) .compare(city, o.city, Ordering.from(String.CASE_INSENSITIVE_ORDER).nullsFirst()) .compare(region, o.region, Ordering.from(String.CASE_INSENSITIVE_ORDER).nullsFirst()) .compare( postalCode, o.postalCode, Ordering.from(String.CASE_INSENSITIVE_ORDER).nullsFirst()) .compare(country, o.country, Ordering.from(String.CASE_INSENSITIVE_ORDER).nullsFirst()) .compare( homePhone, o.homePhone, Ordering.from(String.CASE_INSENSITIVE_ORDER).nullsFirst()) .compare( extension, o.extension, Ordering.from(String.CASE_INSENSITIVE_ORDER).nullsFirst()) .compare(reportsTo, o.reportsTo, Ordering.natural().nullsFirst()) .result(); if (diff != 0) return diff; if (photo == null) return o.photo == null ? 0 : -1; if (o.photo == null) return 1; return UnsignedBytes.lexicographicalComparator().compare(photo, o.photo); }
@Test public void testEqualsPerformance() { boolean testEnabled = false; if (testEnabled) { final int ITERATIONS = 10000000; long start1 = System.currentTimeMillis(); for (int i = 0; i < ITERATIONS; i++) { Comparator<byte[]> comparator = UnsignedBytes.lexicographicalComparator(); comparator.compare(wrapper1.getData(), wrapper2.getData()); } System.out.println(System.currentTimeMillis() - start1 + "ms"); long start2 = System.currentTimeMillis(); for (int i = 0; i < ITERATIONS; i++) { Arrays.equals(wrapper1.getData(), wrapper2.getData()); } System.out.println(System.currentTimeMillis() - start2 + "ms"); long start3 = System.currentTimeMillis(); for (int i = 0; i < ITERATIONS; i++) { FastByteComparisons.compareTo( wrapper1.getData(), 0, wrapper1.getData().length, wrapper2.getData(), 0, wrapper1.getData().length); } System.out.println(System.currentTimeMillis() - start3 + "ms"); } }
@Test public void testRangesPrefixed() throws Exception { File dir0 = Files.createTempDir(); VersionedPartitionName versionedPartitionName = new VersionedPartitionName( new PartitionName(false, "r1".getBytes(), "t1".getBytes()), VersionedPartitionName.STATIC_VERSION); BerkeleyDBWALIndex index = getIndex(dir0, versionedPartitionName); index.merge( (TxKeyPointerStream stream) -> { for (long i = 0; i < 64; i++) { byte[] prefix = {0, (byte) (i % 4)}; byte[] key = {0, 0, (byte) (i % 2), (byte) i}; if (!stream.stream( i, prefix, key, null, System.currentTimeMillis(), false, Long.MAX_VALUE, i)) { return false; } } return true; }, null); int[] count = new int[1]; byte[] fromPrefix = {0, 1}; byte[] toPrefix = {0, 2}; index.rangeScan( fromPrefix, new byte[0], toPrefix, new byte[0], (prefix, key, timestamp, tombstoned, version, fp, hasValue, value) -> { count[0]++; Assert.assertTrue( UnsignedBytes.lexicographicalComparator().compare(fromPrefix, prefix) <= 0); Assert.assertTrue( UnsignedBytes.lexicographicalComparator().compare(prefix, toPrefix) < 0); // System.out.println("prefix: " + Arrays.toString(prefix) + " key: " + // Arrays.toString(key)); return true; }, true); Assert.assertEquals(count[0], 16); }
private boolean isLatestValueEmpty(Cell cell, PeekingIterator<RowResult<Value>> values) { while (values.hasNext()) { RowResult<Value> result = values.peek(); int comparison = UnsignedBytes.lexicographicalComparator().compare(cell.getRowName(), result.getRowName()); if (comparison == 0) { Value matchingValue = result.getColumns().get(cell.getColumnName()); return matchingValue != null && matchingValue.getContents().length == 0; } else if (comparison < 0) { return false; } else { values.next(); } } return false; }
public class Value { static final Comparator<byte[]> comparator = UnsignedBytes.lexicographicalComparator(); protected Map<String, byte[]> fields; public Value() { fields = new HashMap<String, byte[]>(); } public Value(Value v) { fields = new HashMap<String, byte[]>(v.fields); } public byte[] getField(String field) { return fields.get(field); } public Value setField(String field, byte[] data) { fields.put(field, data); return this; } public Value clearFields() { fields.clear(); return this; } public Set<String> getFields() { return fields.keySet(); } public Map<String, byte[]> getFieldsMap() { return Collections.unmodifiableMap(fields); } /** * Select parts of fields. * * @param fields Parts of fields * @return new value with specified fields */ public Value project(Set<String> fields) { if (ALL_FIELDS == fields) { return new Value(this); } Value v = new Value(); for (String f : fields) { byte[] data = this.fields.get(f); v.setField(f, data); } return v; } @Override public int hashCode() { HashFunction hf = Hashing.murmur3_32(); Hasher hc = hf.newHasher(); for (String key : fields.keySet()) { hc.putString(key, Charsets.UTF_8); } return hc.hash().asInt(); } @Override public boolean equals(Object o) { if (!(o instanceof Value)) { return false; } Value other = (Value) o; if (fields.size() != other.fields.size()) { return false; } for (String f : fields.keySet()) { byte[] v1 = fields.get(f); byte[] v2 = other.fields.get(f); if (0 != comparator.compare(v1, v2)) { return false; } } return true; } /** * Merge other value. * * @param other Other Value */ public Value merge(Value other) { for (Map.Entry<String, byte[]> entry : other.fields.entrySet()) { if (null == entry.getValue()) { fields.remove(entry.getKey()); } else { fields.put(entry.getKey(), entry.getValue()); } } return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("["); for (Map.Entry<String, byte[]> entry : fields.entrySet()) { String f = entry.getKey(); if (null == f) { f = "NULL"; } String value; if (null == entry.getValue()) { value = "NONE"; } else { value = new String(entry.getValue(), UTF_8); } sb.append("('").append(f).append("'=").append(value).append(")"); } sb.append("]"); return sb.toString(); } }