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 <shawn.ck.y...@gmail.com> 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: commits-unsubscr...@fury.apache.org For additional commands, e-mail: commits-h...@fury.apache.org