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

ctubbsii pushed a commit to branch 2.1
in repository https://gitbox.apache.org/repos/asf/accumulo.git


The following commit(s) were added to refs/heads/2.1 by this push:
     new 7ae2b3355f Limit memory usage when deserializing Mutations (#6495)
7ae2b3355f is described below

commit 7ae2b3355f9b781becc2a8dffc47b4f9c84a99a4
Author: Christopher Tubbs <[email protected]>
AuthorDate: Thu Aug 6 15:48:38 2026 -0400

    Limit memory usage when deserializing Mutations (#6495)
---
 .../java/org/apache/accumulo/core/data/Mutation.java | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/core/src/main/java/org/apache/accumulo/core/data/Mutation.java 
b/core/src/main/java/org/apache/accumulo/core/data/Mutation.java
index 95ee6f4120..3a15e5d94c 100644
--- a/core/src/main/java/org/apache/accumulo/core/data/Mutation.java
+++ b/core/src/main/java/org/apache/accumulo/core/data/Mutation.java
@@ -73,6 +73,13 @@ import com.google.common.base.Preconditions;
  */
 public class Mutation implements Writable {
 
+  // the exact upper boundary for the initial array size doesn't matter, so 
long as it's high enough
+  // to avoid resizing if the user has any reasonable number of column updates 
in a single mutation;
+  // this value, near 100_000, was chosen to try to optimize memory allocation 
to typical hardware
+  // page sizes, accounting for 16 bytes overhead for the array, that works 
with either 32-bit
+  // compressed object references or native 64-bit references, while keeping 
the value reasonable
+  private static final int MAX_INITIAL_ARRAY_SIZE = 100_348;
+
   /**
    * Internally, this class keeps most mutation data in a byte buffer. If a 
cell value put into a
    * mutation exceeds this size, then it is stored in a separate buffer, and a 
reference to it is
@@ -1255,19 +1262,22 @@ public class Mutation implements Writable {
   public List<ColumnUpdate> getUpdates() {
     serialize();
 
-    UnsynchronizedBuffer.Reader in = new UnsynchronizedBuffer.Reader(data);
-
     if (updates == null) {
+      var in = new UnsynchronizedBuffer.Reader(data);
+
       if (entries == 1) {
         updates = Collections.singletonList(deserializeColumnUpdate(in));
       } else {
-        ColumnUpdate[] tmpUpdates = new ColumnUpdate[entries];
+        // if the number of column updates is excessive, then the performance 
will be slowed due to
+        // resizing the ArrayList to meet the requested capacity
+        int initialArraySize = Math.min(entries, MAX_INITIAL_ARRAY_SIZE);
+        var tmpUpdates = new ArrayList<ColumnUpdate>(initialArraySize);
 
         for (int i = 0; i < entries; i++) {
-          tmpUpdates[i] = deserializeColumnUpdate(in);
+          tmpUpdates.add(deserializeColumnUpdate(in));
         }
 
-        updates = Arrays.asList(tmpUpdates);
+        updates = tmpUpdates;
       }
     }
 

Reply via email to