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

andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git


The following commit(s) were added to refs/heads/main by this push:
     new 4e84ba3728 ByteBufferLib: use bulk get/put APIs
     new 4933549244 Merge pull request #1800 from lucasvr/main
4e84ba3728 is described below

commit 4e84ba3728746e5d40c8892e09177887bf62d467
Author: Lucas C. Villa Real <luca...@gmail.com>
AuthorDate: Thu Mar 16 12:02:52 2023 -0300

    ByteBufferLib: use bulk get/put APIs
    
    CPU profiling of a brand new installation of jena-fuseki shows that
    ~75% of the time spent by `s-put` (when ingesting Turtle tuples via
    SPARQL) relates to the execution of `ByteBufferLib.bbcopy2()` -- often
    as part of B+tree operations such as `BPTreeNode.internalDelete()`.
    
    `bbcopy2()` and `bbcopy1()` perform data copy from a source ByteBuffer
    to a destination ByteBuffer by reading/writing one byte at a time, which
    is not very efficient. In addition, `bbcopy1()` makes a poor use of data
    cache prefetches, as it iterates the ByteBuffers in reverse order.
    
    This commit replaces the implementation of these two functions by one
    that reads the input data in bulk mode into a dynamically allocated byte
    array and then writes its contents to the destination buffer using a bulk
    `put()` operation.
    
    The speedup gains introduced by these code changes are consistent
    regardless of the number of triples being ingested into Jena:
    
    Input file: 1.2GB with 1.75M triples
    Original ingestion time: 544 secs
    After changes to bbcopy: 454 secs (1.19x speedup)
    
    Input file: 21MB with 154k triples
    Original ingestion time: 7.4 secs
    After changes to bbcopy: 6.0 secs (1.24x speedup)
    
    Refs #1800
---
 .../org/apache/jena/atlas/lib/ByteBufferLib.java   | 42 ++++++++++++----------
 1 file changed, 24 insertions(+), 18 deletions(-)

diff --git 
a/jena-base/src/main/java/org/apache/jena/atlas/lib/ByteBufferLib.java 
b/jena-base/src/main/java/org/apache/jena/atlas/lib/ByteBufferLib.java
index 54a542a169..42714491a0 100644
--- a/jena-base/src/main/java/org/apache/jena/atlas/lib/ByteBufferLib.java
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/ByteBufferLib.java
@@ -122,28 +122,24 @@ public class ByteBufferLib {
             return ;
         }
 
-        if ( src < dst )
-            bbcopy1(bb, src, dst, length, slotLen) ;
-        else
-            bbcopy2(bb, src, dst, length, slotLen) ;
+        bbcopyBulk(bb, src, dst, length, slotLen) ;
     }
 
-    private final static void bbcopy1(ByteBuffer bb, int src, int dst, int 
length, int slotLen) {
+    private final static void bbcopyBulk(ByteBuffer bb, int src, int dst, int 
length, int slotLen) {
         int bDst = dst * slotLen ;
         int bSrc = src * slotLen ;
         int bLen = length * slotLen ;
-        // src < dst so top dst is not in the overlap : work backwards
-        for ( int i = bLen - 1 ; i >= 0 ; i-- )
-            bb.put(bDst + i, bb.get(bSrc + i)) ;
-    }
 
-    private final static void bbcopy2(ByteBuffer bb, int src, int dst, int 
length, int slotLen) {
-        int bDst = dst * slotLen ;
-        int bSrc = src * slotLen ;
-        int bLen = length * slotLen ;
-        // src > dst so dst[0] is not in the overlap
-        for ( int i = 0 ; i < bLen ; i++ )
-            bb.put(bDst + i, bb.get(bSrc + i)) ;
+        byte[] srcBytes = new byte[bLen];
+
+        int pos = bb.position();
+        bb.position(bSrc);
+        bb.get(srcBytes, 0, bLen);
+
+        bb.position(bDst);
+        bb.put(srcBytes, 0, bLen);
+        bb.position(pos);
+
     }
 
     public final static void bbcopy(ByteBuffer bb1, int src, ByteBuffer bb2, 
int dst, int length, int slotLen) {
@@ -158,8 +154,18 @@ public class ByteBufferLib {
         int bDst = dst * slotLen ;
         int bLen = length * slotLen ;
 
-        for ( int i = 0 ; i < bLen ; i++ )
-            bb2.put(bDst + i, bb1.get(bSrc + i)) ;
+        // Use bulk get/put to speed up data copy
+        byte[] srcBytes = new byte[bLen];
+
+        int pos1 = bb1.position();
+        bb1.position(bSrc);
+        bb1.get(srcBytes, 0, bLen);
+        bb1.position(pos1);
+
+        int pos2 = bb2.position();
+        bb2.position(bDst);
+        bb2.put(srcBytes, 0, bLen);
+        bb2.position(pos2);
     }
 
     final public static void bbfill(ByteBuffer bb, int fromIdx, int toIdx, 
byte fillValue, int slotLen) {

Reply via email to