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/fury.git


The following commit(s) were added to refs/heads/main by this push:
     new 676c5742 perf(java): Improve performance by using System.arraycopy to 
copy between byte arrays (#2101)
676c5742 is described below

commit 676c5742b94ec30137cf282b7ebfd69186d9f8b6
Author: Seppe Volkaerts <[email protected]>
AuthorDate: Sun Mar 16 05:49:30 2025 +0100

    perf(java): Improve performance by using System.arraycopy to copy between 
byte arrays (#2101)
    
    ## What does this PR do?
    
    Try to use `System.arraycopy` when copying between byte arrays. This
    significantly increases performance, in our use case serialization is
    twice as fast (serializing/deserializing 1M complex strucutures using
    (de)serializeJavaObject in parallel). When using Platform.copyMemory,
    the JDK is doing a lot of type checking to see if it's a byte array,
    causing a visible slowdown. `Unsafe.memoryCopy` implementation was
    changed in Java 9 from a native method to a method calling the internal
    unsafe method containing the reflection checks.
    
    There are a few places where System.arraycopy is already used, referring
    to it being faster on certain JDK implementations. Tested our use case
    on a macbook with arm64 cpu against zulu 21 and open-jdk 23.
    
    
    
![image](https://github.com/user-attachments/assets/ce4a2c9d-e7b7-49ae-867d-68eadbe8a140)
    
    ## Does this PR introduce any user-facing change?
    
    - [ ] Does this PR introduce any public API change?
    - [ ] Does this PR introduce any binary protocol compatibility change?
    
    ## Benchmark
    I tried to reproduce the performance impact through one on existing
    benchmarks `UserTypeSerializeSuite.fury_serialize`, however I didn't see
    a difference here.
    
    Signed-off-by: Seppe Volkaerts <[email protected]>
---
 .../java/org/apache/fury/memory/MemoryBuffer.java  | 56 +++++++++++++---------
 1 file changed, 34 insertions(+), 22 deletions(-)

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 d5003e36..e9f4ba11 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
@@ -313,17 +313,23 @@ public final class MemoryBuffer {
   }
 
   public void get(int index, byte[] dst, int offset, int length) {
-    final long pos = address + index;
-    if ((index
-            | offset
-            | length
-            | (offset + length)
-            | (dst.length - (offset + length))
-            | addressLimit - length - pos)
-        < 0) {
-      throwOOBException();
+    final byte[] heapMemory = this.heapMemory;
+    if (heapMemory != null) {
+      // System.arraycopy faster for some jdk than Unsafe.
+      System.arraycopy(heapMemory, heapOffset + index, dst, offset, length);
+    } else {
+      final long pos = address + index;
+      if ((index
+              | offset
+              | length
+              | (offset + length)
+              | (dst.length - (offset + length))
+              | addressLimit - length - pos)
+          < 0) {
+        throwOOBException();
+      }
+      Platform.copyMemory(null, pos, dst, Platform.BYTE_ARRAY_OFFSET + offset, 
length);
     }
-    Platform.copyMemory(heapMemory, pos, dst, Platform.BYTE_ARRAY_OFFSET + 
offset, length);
   }
 
   public void get(int offset, ByteBuffer target, int numBytes) {
@@ -378,19 +384,25 @@ public final class MemoryBuffer {
   }
 
   public void put(int index, byte[] src, int offset, int length) {
-    final long pos = address + index;
-    // check the byte array offset and length
-    if ((index
-            | offset
-            | length
-            | (offset + length)
-            | (src.length - (offset + length))
-            | addressLimit - length - pos)
-        < 0) {
-      throwOOBException();
+    final byte[] heapMemory = this.heapMemory;
+    if (heapMemory != null) {
+      // System.arraycopy faster for some jdk than Unsafe.
+      System.arraycopy(src, offset, heapMemory, heapOffset + index, length);
+    } else {
+      final long pos = address + index;
+      // check the byte array offset and length
+      if ((index
+              | offset
+              | length
+              | (offset + length)
+              | (src.length - (offset + length))
+              | addressLimit - length - pos)
+          < 0) {
+        throwOOBException();
+      }
+      final long arrayAddress = Platform.BYTE_ARRAY_OFFSET + offset;
+      Platform.copyMemory(src, arrayAddress, null, pos, length);
     }
-    final long arrayAddress = Platform.BYTE_ARRAY_OFFSET + offset;
-    Platform.copyMemory(src, arrayAddress, heapMemory, pos, length);
   }
 
   public byte getByte(int index) {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to