raminqaf commented on code in PR #29636:
URL: https://github.com/apache/flink/pull/29636#discussion_r4388725241


##########
flink-core/src/main/java/org/apache/flink/types/variant/BinaryVariant.java:
##########
@@ -341,32 +347,68 @@ private void checkType(Type expected, Type actual) {
     // Find the field value whose key is equal to `key`. Return null if the 
key is not found.
     // It is only legal to call it when `getType()` is `Type.OBJECT`.
     private BinaryVariant getFieldByKey(String key) {
-        byte[] keyBytes = encodeKey(key);
-        return handleObject(
-                value,
-                pos,
-                (size, idSize, offsetSize, idStart, offsetStart, dataStart) -> 
{
-                    int index;
-                    // Use linear search for a short list. Switch to binary 
search when the length
-                    // reaches `BINARY_SEARCH_THRESHOLD`.
-                    if (size < BINARY_SEARCH_THRESHOLD) {
-                        index = findFieldLinear(keyBytes, size, idSize, 
idStart);
-                    } else {
-                        index = findFieldBinary(keyBytes, size, idSize, 
idStart);
-                        // Objects that earlier Flink versions wrote are 
sorted in UTF-16 order
-                        // instead. Only a miss for a key with a code point 
from U+E000 up can be
-                        // wrong there, see `hasCodePointFromE000`. Such a 
miss scans all fields,
-                        // because an object does not record which order it 
uses.
-                        if (index < 0 && hasCodePointFromE000(keyBytes)) {
-                            index = findFieldLinear(keyBytes, size, idSize, 
idStart);
-                        }
-                    }
-                    if (index < 0) {
-                        return null;
-                    }
-                    int offset = readUnsigned(value, offsetStart + offsetSize 
* index, offsetSize);
-                    return new BinaryVariant(value, metadata, dataStart + 
offset);
-                });
+        return getFieldByKey(encodeKey(key), null);
+    }
+
+    /**
+     * Returns the field whose key has the UTF-8 bytes {@code key}, or null if 
there is none.
+     *
+     * <p>A {@code getter} remembers the index at which it last found its key. 
That field is checked
+     * first, so a correct guess skips the search and a wrong one costs one 
key comparison.
+     *
+     * @throws VariantTypeException if the variant is not an object
+     */
+    @Nullable
+    BinaryVariant getFieldByKey(byte[] key, @Nullable VariantFieldGetter 
getter) {
+        // Decode the header here instead of in `handleObject` and its 
capturing lambda, so that a
+        // lookup allocates nothing but the returned view.
+        int typeInfo = objectTypeInfo(value, pos);
+        int sizeBytes = objectSizeBytes(typeInfo);
+        int size = readUnsigned(value, pos + 1, sizeBytes);
+        int idSize = objectIdSize(typeInfo);
+        int idStart = pos + 1 + sizeBytes;
+        // Read the remembered index once, so that a getter shared between 
threads only ever
+        // returns a field whose key it checked.
+        int index = getter == null ? 0 : getter.lastIndex;
+        if (getter == null || !hasKeyAt(key, index, size, idSize, idStart)) {
+            index = findField(key, size, idSize, idStart);
+            if (index < 0) {
+                return null;
+            }
+            if (getter != null) {
+                getter.lastIndex = index;
+            }
+        }
+        int offsetSize = objectOffsetSize(typeInfo);
+        int offsetStart = idStart + size * idSize;
+        int dataStart = offsetStart + (size + 1) * offsetSize;
+        int offset = readUnsigned(value, offsetStart + offsetSize * index, 
offsetSize);
+        return new BinaryVariant(value, metadata, dataStart + offset);
+    }
+
+    private boolean hasKeyAt(byte[] key, int index, int size, int idSize, int 
idStart) {
+        return index < size
+                && metadataKeyEquals(
+                        metadata, readUnsigned(value, idStart + idSize * 
index, idSize), key);
+    }
+
+    /**
+     * Like {@code findFieldLinear}, but uses binary search from {@code 
BINARY_SEARCH_THRESHOLD}
+     * fields on.
+     */
+    private int findField(byte[] key, int size, int idSize, int idStart) {
+        if (size < BINARY_SEARCH_THRESHOLD) {
+            return findFieldLinear(key, size, idSize, idStart);
+        }
+        int index = findFieldBinary(key, size, idSize, idStart);
+        // Objects that earlier Flink versions wrote are sorted in UTF-16 
order instead. Only a miss
+        // for a key with a code point from U+E000 up can be wrong there, see
+        // `hasCodePointFromE000`. Such a miss scans all fields, because an 
object does not record
+        // which order it uses.
+        if (index < 0 && hasCodePointFromE000(key)) {
+            index = findFieldLinear(key, size, idSize, idStart);
+        }
+        return index;
     }

Review Comment:
   Only refactored and moved into a new method



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to