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;
}
}