Github user Ben-Zvi commented on a diff in the pull request:
https://github.com/apache/drill/pull/938#discussion_r138437442
--- Diff:
exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/aggregate/HashAggTemplate.java
---
@@ -646,6 +687,46 @@ public AggOutcome doWork() {
}
/**
+ * Use reserved values memory (if available) to try and preemp an OOM
+ */
+ private void useReservedValuesMemory() {
+ // try to preempt an OOM by using the reserved memory
+ long reservedMemory = reserveValueBatchMemory;
+ if ( reservedMemory > 0 ) { allocator.setLimit(allocator.getLimit() +
reservedMemory); }
+
+ reserveValueBatchMemory = 0;
+ }
+ /**
+ * Use reserved outgoing output memory (if available) to try and
preemp an OOM
+ */
+ private void useReservedOutgoingMemory() {
+ // try to preempt an OOM by using the reserved memory
+ long reservedMemory = reserveOutgoingMemory;
+ if ( reservedMemory > 0 ) { allocator.setLimit(allocator.getLimit() +
reservedMemory); }
--- End diff --
Because the first uncontrolled memory allocation happens when inserting
into the hash table (i.e. put()). Given this "uncontrollability", better OOM
there (which we can handle, by spilling and retrying). Now if all the memory
was "given" in the limit, the put() may not OOM, but leave too little available
memory to continue (i.e. to create a values batch, or an outgoing batch) --
these situations we can not handle.
By subtracting from the limit a "reserve" for these two batches, we may
force a put() OOM early (but that's OK). But we also ensure that the following
two batches could be allocated. In some way this is similar to having multiple
dedicated allocators, only simpler.
Adding or subtracting is just an operation on a local field; no
performance effect in any way. Also by using a single allocator we can handle
cases like a "bump" in a batch size (which may exceed pre-allocation in a
dedicated separate allocator).
---