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 4c60eb97 feat(java): optimize read char/short jvm jit inline (#1471)
4c60eb97 is described below
commit 4c60eb9780ec51ffe1aac3ee2da594c0762799e0
Author: Shawn Yang <[email protected]>
AuthorDate: Sat Apr 6 19:53:53 2024 +0800
feat(java): optimize read char/short jvm jit inline (#1471)
- optimize read char jvm jit inline by separate little/big endian
methods
- optimize read short jvm jit inline by separate little/big endian
methods
- generate unsafe get short code online
- generate unsafe get char code online
---
.../fury/builder/BaseObjectCodecBuilder.java | 5 +-
.../java/org/apache/fury/builder/CodecBuilder.java | 23 ++++-
.../java/org/apache/fury/memory/MemoryBuffer.java | 111 +++++++++++----------
.../org/apache/fury/memory/MemoryBufferTest.java | 2 +-
4 files changed, 84 insertions(+), 57 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 a27abbab..f92e076e 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
@@ -40,7 +40,6 @@ import static
org.apache.fury.type.TypeUtils.PRIMITIVE_BYTE_TYPE;
import static org.apache.fury.type.TypeUtils.PRIMITIVE_DOUBLE_TYPE;
import static org.apache.fury.type.TypeUtils.PRIMITIVE_FLOAT_TYPE;
import static org.apache.fury.type.TypeUtils.PRIMITIVE_INT_TYPE;
-import static org.apache.fury.type.TypeUtils.PRIMITIVE_SHORT_TYPE;
import static org.apache.fury.type.TypeUtils.PRIMITIVE_VOID_TYPE;
import static org.apache.fury.type.TypeUtils.SET_TYPE;
import static org.apache.fury.type.TypeUtils.getElementType;
@@ -1131,9 +1130,9 @@ public abstract class BaseObjectCodecBuilder extends
CodecBuilder {
} else if (cls == boolean.class || cls == Boolean.class) {
return new Invoke(buffer, "readBoolean", PRIMITIVE_BOOLEAN_TYPE);
} else if (cls == char.class || cls == Character.class) {
- return new Invoke(buffer, "readChar", TypeToken.of(char.class));
+ return readChar(buffer);
} else if (cls == short.class || cls == Short.class) {
- return new Invoke(buffer, "readShort", PRIMITIVE_SHORT_TYPE);
+ return readShort(buffer);
} else if (cls == int.class || cls == Integer.class) {
return fury.compressInt() ? readVarInt(buffer) : readInt(buffer);
} else if (cls == long.class || cls == Long.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 121c6ecb..746a698d 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
@@ -587,11 +587,20 @@ public abstract class CodecBuilder {
}
protected Expression unsafeGetChar(Expression base, Expression pos) {
- return new StaticInvoke(MemoryBuffer.class, "unsafeGetChar",
PRIMITIVE_CHAR_TYPE, base, pos);
+ StaticInvoke expr = new StaticInvoke(Platform.class, "getChar",
PRIMITIVE_CHAR_TYPE, base, pos);
+ if (!Platform.IS_LITTLE_ENDIAN) {
+ expr = new StaticInvoke(Character.class, "reverseBytes",
PRIMITIVE_CHAR_TYPE, expr.inline());
+ }
+ return expr;
}
protected Expression unsafeGetShort(Expression base, Expression pos) {
- return new StaticInvoke(MemoryBuffer.class, "unsafeGetShort",
PRIMITIVE_SHORT_TYPE, base, pos);
+ StaticInvoke expr =
+ new StaticInvoke(Platform.class, "getShort", PRIMITIVE_SHORT_TYPE,
base, pos);
+ if (!Platform.IS_LITTLE_ENDIAN) {
+ expr = new StaticInvoke(Short.class, "reverseBytes",
PRIMITIVE_SHORT_TYPE, expr.inline());
+ }
+ return expr;
}
protected Expression unsafeGetInt(Expression base, Expression pos) {
@@ -619,6 +628,16 @@ public abstract class CodecBuilder {
MemoryBuffer.class, "unsafeGetDouble", PRIMITIVE_DOUBLE_TYPE, base,
pos);
}
+ protected Expression readChar(Expression buffer) {
+ String func = Platform.IS_LITTLE_ENDIAN ? "readCharOnLE" : "readCharOnBE";
+ return new Invoke(buffer, func, PRIMITIVE_CHAR_TYPE);
+ }
+
+ protected Expression readShort(Expression buffer) {
+ String func = Platform.IS_LITTLE_ENDIAN ? "readShortOnLE" :
"readShortOnBE";
+ return new Invoke(buffer, func, PRIMITIVE_SHORT_TYPE);
+ }
+
protected Expression readInt(Expression buffer) {
String func = Platform.IS_LITTLE_ENDIAN ? "readIntOnLE" : "readIntOnBE";
return new Invoke(buffer, func, PRIMITIVE_INT_TYPE);
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 105fcd8c..155b8df6 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
@@ -505,33 +505,6 @@ public final class MemoryBuffer {
}
}
- public char unsafeGetCharN(int index) {
- final long pos = address + index;
- return UNSAFE.getChar(heapMemory, pos);
- }
-
- public char unsafeGetChar(int index) {
- final long pos = address + index;
- if (LITTLE_ENDIAN) {
- return UNSAFE.getChar(heapMemory, pos);
- } else {
- return Character.reverseBytes(UNSAFE.getChar(heapMemory, pos));
- }
- }
-
- public static char unsafeGetChar(Object o, long pos) {
- if (LITTLE_ENDIAN) {
- return UNSAFE.getChar(o, pos);
- } else {
- return Character.reverseBytes(UNSAFE.getChar(o, pos));
- }
- }
-
- public void unsafePutCharN(int index, char value) {
- final long pos = address + index;
- UNSAFE.putChar(heapMemory, pos, value);
- }
-
public void unsafePutChar(int index, char value) {
final long pos = address + index;
if (LITTLE_ENDIAN) {
@@ -549,12 +522,6 @@ public final class MemoryBuffer {
}
}
- public short getShortN(int index) {
- final long pos = address + index;
- checkPosition(index, pos, 2);
- return UNSAFE.getShort(heapMemory, pos);
- }
-
/** Get short in big endian order from provided buffer. */
public static short getShortB(byte[] b, int off) {
return (short) ((b[off + 1] & 0xFF) + (b[off] << 8));
@@ -597,11 +564,6 @@ public final class MemoryBuffer {
}
}
- public short unsafeGetShortN(int index) {
- final long pos = address + index;
- return UNSAFE.getShort(heapMemory, pos);
- }
-
public short unsafeGetShort(int index) {
final long pos = address + index;
if (LITTLE_ENDIAN) {
@@ -611,19 +573,6 @@ public final class MemoryBuffer {
}
}
- public static short unsafeGetShort(Object o, long offset) {
- if (LITTLE_ENDIAN) {
- return UNSAFE.getShort(o, offset);
- } else {
- return Short.reverseBytes(UNSAFE.getShort(o, offset));
- }
- }
-
- public void unsafePutShortN(int index, short value) {
- final long pos = address + index;
- UNSAFE.putShort(heapMemory, pos, value);
- }
-
public void unsafePutShort(int index, short value) {
final long pos = address + index;
if (LITTLE_ENDIAN) {
@@ -2131,6 +2080,36 @@ public final class MemoryBuffer {
}
}
+ // Reduce method body for better inline in the caller.
+ @CodegenInvoke
+ public char readCharOnLE() {
+ int readerIdx = readerIndex;
+ // use subtract to avoid overflow
+ int remaining = size - readerIdx;
+ if (remaining < 2) {
+ throw new IndexOutOfBoundsException(
+ String.format(
+ "readerIndex(%d) + length(%d) exceeds size(%d): %s", readerIdx,
2, size, this));
+ }
+ readerIndex = readerIdx + 2;
+ return UNSAFE.getChar(heapMemory, address + readerIdx);
+ }
+
+ // Reduce method body for better inline in the caller.
+ @CodegenInvoke
+ public char readCharOnBE() {
+ int readerIdx = readerIndex;
+ // use subtract to avoid overflow
+ int remaining = size - readerIdx;
+ if (remaining < 2) {
+ throw new IndexOutOfBoundsException(
+ String.format(
+ "readerIndex(%d) + length(%d) exceeds size(%d): %s", readerIdx,
2, size, this));
+ }
+ readerIndex = readerIdx + 2;
+ return Character.reverseBytes(UNSAFE.getChar(heapMemory, address +
readerIdx));
+ }
+
public short readShort() {
int readerIdx = readerIndex;
// use subtract to avoid overflow
@@ -2148,6 +2127,36 @@ public final class MemoryBuffer {
}
}
+ // Reduce method body for better inline in the caller.
+ @CodegenInvoke
+ public short readShortOnLE() {
+ int readerIdx = readerIndex;
+ // use subtract to avoid overflow
+ int remaining = size - readerIdx;
+ if (remaining < 2) {
+ throw new IndexOutOfBoundsException(
+ String.format(
+ "readerIndex(%d) + length(%d) exceeds size(%d): %s", readerIdx,
2, size, this));
+ }
+ readerIndex = readerIdx + 2;
+ return UNSAFE.getShort(heapMemory, address + readerIdx);
+ }
+
+ // Reduce method body for better inline in the caller.
+ @CodegenInvoke
+ public short readShortOnBE() {
+ int readerIdx = readerIndex;
+ // use subtract to avoid overflow
+ int remaining = size - readerIdx;
+ if (remaining < 2) {
+ throw new IndexOutOfBoundsException(
+ String.format(
+ "readerIndex(%d) + length(%d) exceeds size(%d): %s", readerIdx,
2, size, this));
+ }
+ readerIndex = readerIdx + 2;
+ return Short.reverseBytes(UNSAFE.getShort(heapMemory, address +
readerIdx));
+ }
+
public int readInt() {
int readerIdx = readerIndex;
// use subtract to avoid overflow
diff --git
a/java/fury-core/src/test/java/org/apache/fury/memory/MemoryBufferTest.java
b/java/fury-core/src/test/java/org/apache/fury/memory/MemoryBufferTest.java
index 6b1cc7fa..78fa41ba 100644
--- a/java/fury-core/src/test/java/org/apache/fury/memory/MemoryBufferTest.java
+++ b/java/fury-core/src/test/java/org/apache/fury/memory/MemoryBufferTest.java
@@ -83,7 +83,7 @@ public class MemoryBufferTest {
pos -= 4;
assertEquals(MemoryBuffer.unsafeGetInt(heapMemory, pos),
Integer.MIN_VALUE);
pos -= 2;
- assertEquals(MemoryBuffer.unsafeGetShort(heapMemory, pos),
Short.MAX_VALUE);
+ assertEquals(buffer.getShort((int) (pos - Platform.BYTE_ARRAY_OFFSET)),
Short.MAX_VALUE);
pos -= 1;
assertEquals(MemoryBuffer.unsafeGet(heapMemory, pos), Byte.MIN_VALUE);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]