This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-fury.git


The following commit(s) were added to refs/heads/main by this push:
     new d73c3d9f feat(java): reduce readInt/readVarInt code size for for jvm 
jit inline (#1469)
d73c3d9f is described below

commit d73c3d9f8c0c750ffe718a1553cd10c45e605c57
Author: Shawn Yang <shawn.ck.y...@gmail.com>
AuthorDate: Sat Apr 6 18:59:32 2024 +0800

    feat(java): reduce readInt/readVarInt code size for for jvm jit inline 
(#1469)
    
    This PR optimizes readVarInt/readInt performance by reduce code size of
    readVarInt for better jvm jit
---
 .../fury/builder/BaseObjectCodecBuilder.java       |   3 +-
 .../java/org/apache/fury/builder/CodecBuilder.java |  16 ++-
 .../apache/fury/builder/ObjectCodecBuilder.java    |   2 +-
 .../java/org/apache/fury/memory/MemoryBuffer.java  | 118 ++++++++++++++++++++-
 4 files changed, 133 insertions(+), 6 deletions(-)

diff --git 
a/java/fury-core/src/main/java/org/apache/fury/builder/BaseObjectCodecBuilder.java
 
b/java/fury-core/src/main/java/org/apache/fury/builder/BaseObjectCodecBuilder.java
index 0b0b7594..a27abbab 100644
--- 
a/java/fury-core/src/main/java/org/apache/fury/builder/BaseObjectCodecBuilder.java
+++ 
b/java/fury-core/src/main/java/org/apache/fury/builder/BaseObjectCodecBuilder.java
@@ -1135,8 +1135,7 @@ public abstract class BaseObjectCodecBuilder extends 
CodecBuilder {
       } else if (cls == short.class || cls == Short.class) {
         return new Invoke(buffer, "readShort", PRIMITIVE_SHORT_TYPE);
       } else if (cls == int.class || cls == Integer.class) {
-        String func = fury.compressInt() ? "readVarInt" : "readInt";
-        return new Invoke(buffer, func, PRIMITIVE_INT_TYPE);
+        return fury.compressInt() ? readVarInt(buffer) : readInt(buffer);
       } else if (cls == long.class || cls == Long.class) {
         return LongSerializer.readLong(buffer, fury.longEncoding());
       } else if (cls == float.class || cls == Float.class) {
diff --git 
a/java/fury-core/src/main/java/org/apache/fury/builder/CodecBuilder.java 
b/java/fury-core/src/main/java/org/apache/fury/builder/CodecBuilder.java
index 3ce014bc..457d41bf 100644
--- a/java/fury-core/src/main/java/org/apache/fury/builder/CodecBuilder.java
+++ b/java/fury-core/src/main/java/org/apache/fury/builder/CodecBuilder.java
@@ -595,7 +595,11 @@ public abstract class CodecBuilder {
   }
 
   protected Expression unsafeGetInt(Expression base, Expression pos) {
-    return new StaticInvoke(MemoryBuffer.class, "unsafeGetInt", 
PRIMITIVE_INT_TYPE, base, pos);
+    StaticInvoke expr = new StaticInvoke(Platform.class, "getInt", 
PRIMITIVE_INT_TYPE, base, pos);
+    if (!Platform.IS_LITTLE_ENDIAN) {
+      expr = new StaticInvoke(Integer.class, "reverseBytes", 
PRIMITIVE_INT_TYPE, expr.inline());
+    }
+    return expr;
   }
 
   protected Expression unsafeGetLong(Expression base, Expression pos) {
@@ -610,4 +614,14 @@ public abstract class CodecBuilder {
     return new StaticInvoke(
         MemoryBuffer.class, "unsafeGetDouble", PRIMITIVE_DOUBLE_TYPE, base, 
pos);
   }
+
+  protected Expression readInt(Expression buffer) {
+    String func = Platform.IS_LITTLE_ENDIAN ? "readIntOnLE" : "readIntOnBE";
+    return new Invoke(buffer, func, PRIMITIVE_INT_TYPE);
+  }
+
+  protected Expression readVarInt(Expression buffer) {
+    String func = Platform.IS_LITTLE_ENDIAN ? "readVarIntOnLE" : 
"readVarIntOnBE";
+    return new Invoke(buffer, func, PRIMITIVE_INT_TYPE);
+  }
 }
diff --git 
a/java/fury-core/src/main/java/org/apache/fury/builder/ObjectCodecBuilder.java 
b/java/fury-core/src/main/java/org/apache/fury/builder/ObjectCodecBuilder.java
index 37365f9d..6731c313 100644
--- 
a/java/fury-core/src/main/java/org/apache/fury/builder/ObjectCodecBuilder.java
+++ 
b/java/fury-core/src/main/java/org/apache/fury/builder/ObjectCodecBuilder.java
@@ -695,7 +695,7 @@ public class ObjectCodecBuilder extends 
BaseObjectCodecBuilder {
               compressStarted = true;
               addIncReaderIndexExpr(groupExpressions, buffer, acc);
             }
-            fieldValue = new Invoke(buffer, "readVarInt", PRIMITIVE_INT_TYPE);
+            fieldValue = readVarInt(buffer);
           }
         } else if (clz == long.class) {
           if (!fury.compressLong()) {
diff --git 
a/java/fury-core/src/main/java/org/apache/fury/memory/MemoryBuffer.java 
b/java/fury-core/src/main/java/org/apache/fury/memory/MemoryBuffer.java
index 6c933318..97285991 100644
--- a/java/fury-core/src/main/java/org/apache/fury/memory/MemoryBuffer.java
+++ b/java/fury-core/src/main/java/org/apache/fury/memory/MemoryBuffer.java
@@ -1223,9 +1223,94 @@ public final class MemoryBuffer {
   }
 
   /** Reads the 1-5 byte int part of a varint. */
+  @CodegenInvoke
   public int readVarInt() {
-    int r = readPositiveVarInt();
-    return (r >>> 1) ^ -(r & 1);
+    if (LITTLE_ENDIAN) {
+      return readVarIntOnLE();
+    } else {
+      return readVarIntOnBE();
+    }
+  }
+
+  /** Reads the 1-5 byte as a varint on a little endian mache. */
+  @CodegenInvoke
+  public int readVarIntOnLE() {
+    // noinspection Duplicates
+    int readIdx = readerIndex;
+    int result;
+    if (size - readIdx < 5) {
+      result = readPositiveVarIntSlow();
+    } else {
+      long address = this.address;
+      // | 1bit + 7bits | 1bit + 7bits | 1bit + 7bits | 1bit + 7bits |
+      int fourByteValue = UNSAFE.getInt(heapMemory, address + readIdx);
+      // Duplicate and manual inline for performance.
+      // noinspection Duplicates
+      readIdx++;
+      result = fourByteValue & 0x7F;
+      if ((fourByteValue & 0x80) != 0) {
+        readIdx++;
+        // 0x3f80: 0b1111111 << 7
+        result |= (fourByteValue >>> 1) & 0x3f80;
+        // 0x8000: 0b1 << 15
+        if ((fourByteValue & 0x8000) != 0) {
+          readIdx++;
+          // 0x1fc000: 0b1111111 << 14
+          result |= (fourByteValue >>> 2) & 0x1fc000;
+          // 0x800000: 0b1 << 23
+          if ((fourByteValue & 0x800000) != 0) {
+            readIdx++;
+            // 0xfe00000: 0b1111111 << 21
+            result |= (fourByteValue >>> 3) & 0xfe00000;
+            if ((fourByteValue & 0x80000000) != 0) {
+              result |= (UNSAFE.getByte(heapMemory, address + readIdx++) & 
0x7F) << 28;
+            }
+          }
+        }
+      }
+      readerIndex = readIdx;
+    }
+    return (result >>> 1) ^ -(result & 1);
+  }
+
+  /** Reads the 1-5 byte as a varint on a big endian mache. */
+  @CodegenInvoke
+  public int readVarIntOnBE() {
+    // noinspection Duplicates
+    int readIdx = readerIndex;
+    int result;
+    if (size - readIdx < 5) {
+      result = readPositiveVarIntSlow();
+    } else {
+      long address = this.address;
+      int fourByteValue = Integer.reverseBytes(UNSAFE.getInt(heapMemory, 
address + readIdx));
+      // Duplicate and manual inline for performance.
+      // noinspection Duplicates
+      readIdx++;
+      result = fourByteValue & 0x7F;
+      if ((fourByteValue & 0x80) != 0) {
+        readIdx++;
+        // 0x3f80: 0b1111111 << 7
+        result |= (fourByteValue >>> 1) & 0x3f80;
+        // 0x8000: 0b1 << 15
+        if ((fourByteValue & 0x8000) != 0) {
+          readIdx++;
+          // 0x1fc000: 0b1111111 << 14
+          result |= (fourByteValue >>> 2) & 0x1fc000;
+          // 0x800000: 0b1 << 23
+          if ((fourByteValue & 0x800000) != 0) {
+            readIdx++;
+            // 0xfe00000: 0b1111111 << 21
+            result |= (fourByteValue >>> 3) & 0xfe00000;
+            if ((fourByteValue & 0x80000000) != 0) {
+              result |= (UNSAFE.getByte(heapMemory, address + readIdx++) & 
0x7F) << 28;
+            }
+          }
+        }
+      }
+      readerIndex = readIdx;
+    }
+    return (result >>> 1) ^ -(result & 1);
   }
 
   /**
@@ -2008,6 +2093,35 @@ public final class MemoryBuffer {
     }
   }
 
+  @CodegenInvoke
+  public int readIntOnLE() {
+    int readerIdx = readerIndex;
+    // use subtract to avoid overflow
+    int remaining = size - readerIdx;
+    if (remaining < 4) {
+      throw new IndexOutOfBoundsException(
+          String.format(
+              "readerIndex(%d) + length(%d) exceeds size(%d): %s", readerIdx, 
4, size, this));
+    }
+    readerIndex = readerIdx + 4;
+    return UNSAFE.getInt(heapMemory, address + readerIdx);
+  }
+
+  // Reduce method body for better inline in the caller.
+  @CodegenInvoke
+  public int readIntOnBE() {
+    int readerIdx = readerIndex;
+    // use subtract to avoid overflow
+    int remaining = size - readerIdx;
+    if (remaining < 4) {
+      throw new IndexOutOfBoundsException(
+          String.format(
+              "readerIndex(%d) + length(%d) exceeds size(%d): %s", readerIdx, 
4, size, this));
+    }
+    readerIndex = readerIdx + 4;
+    return Integer.reverseBytes(UNSAFE.getInt(heapMemory, address + 
readerIdx));
+  }
+
   public long readLong() {
     int readerIdx = readerIndex;
     // use subtract to avoid overflow


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@fury.apache.org
For additional commands, e-mail: commits-h...@fury.apache.org

Reply via email to