use of org.apache.drill.exec.physical.impl.xsort.managed.SortMemoryManager.MergeTask in project drill by axbaretto.
the class TestExternalSortInternals method testMergeCalcsExtreme.
@Test
public void testMergeCalcsExtreme() {
SortConfig sortConfig = new SortConfig(fixture.getFragmentContext().getConfig(), fixture.getFragmentContext().getOptions());
// Force odd situation in which the spill batch is larger
// than memory. Won't actually run, but needed to test
// odd merge case.
long memoryLimit = ONE_MEG / 2;
SortMemoryManager memManager = new SortMemoryManager(sortConfig, memoryLimit);
// Prime the estimates. Batch size is data size, not buffer size.
int rowWidth = (int) memoryLimit;
int rowCount = 1;
int batchSize = rowWidth;
memManager.updateEstimates(batchSize, rowWidth, rowCount);
assertTrue(memManager.getMergeMemoryLimit() < rowWidth);
// Only one spill batch, that batch is above the merge memory limit,
// but nothing useful comes from merging.
MergeTask task = memManager.consolidateBatches(0, 0, 1);
assertEquals(MergeAction.NONE, task.action);
}
use of org.apache.drill.exec.physical.impl.xsort.managed.SortMemoryManager.MergeTask in project drill by axbaretto.
the class TestExternalSortInternals method testMergeLimit.
@Test
public void testMergeLimit() {
// Constrain merge width
int mergeLimitConstraint = 5;
OperatorFixture.Builder builder = new OperatorFixture.Builder();
builder.configBuilder().put(ExecConstants.EXTERNAL_SORT_MERGE_LIMIT, mergeLimitConstraint).build();
FragmentContext fragmentContext = builder.build().getFragmentContext();
SortConfig sortConfig = new SortConfig(fragmentContext.getConfig(), fragmentContext.getOptions());
// Plenty of memory, memory will not be a limit
long memoryLimit = 400 * ONE_MEG;
SortMemoryManager memManager = new SortMemoryManager(sortConfig, memoryLimit);
// Prime the estimates
int rowWidth = 300;
int rowCount = 10000;
int batchSize = rowWidth * rowCount * 2;
memManager.updateEstimates(batchSize, rowWidth, rowCount);
// Pretend merge limit runs, additional in-memory batches
int memBatchCount = 10;
int spillRunCount = mergeLimitConstraint;
long allocMemory = batchSize * memBatchCount;
MergeTask task = memManager.consolidateBatches(allocMemory, memBatchCount, spillRunCount);
assertEquals(MergeAction.SPILL, task.action);
// too many to merge, spill
task = memManager.consolidateBatches(allocMemory, 1, spillRunCount);
assertEquals(MergeAction.SPILL, task.action);
// One more runs than can merge in one go, intermediate merge
task = memManager.consolidateBatches(0, 0, spillRunCount + 1);
assertEquals(MergeAction.MERGE, task.action);
assertEquals(2, task.count);
// Two more spill runs, merge three
task = memManager.consolidateBatches(0, 0, spillRunCount + 2);
assertEquals(MergeAction.MERGE, task.action);
assertEquals(3, task.count);
// Way more than can merge, limit to the constraint
task = memManager.consolidateBatches(0, 0, spillRunCount * 3);
assertEquals(MergeAction.MERGE, task.action);
assertEquals(mergeLimitConstraint, task.count);
}
use of org.apache.drill.exec.physical.impl.xsort.managed.SortMemoryManager.MergeTask in project drill by axbaretto.
the class TestExternalSortInternals method testMergeCalcs.
@Test
public void testMergeCalcs() {
// No artificial merge limit
int mergeLimitConstraint = 100;
OperatorFixture.Builder builder = new OperatorFixture.Builder();
builder.configBuilder().put(ExecConstants.EXTERNAL_SORT_MERGE_LIMIT, mergeLimitConstraint).build();
FragmentContext fragmentContext = builder.build().getFragmentContext();
SortConfig sortConfig = new SortConfig(fragmentContext.getConfig(), fragmentContext.getOptions());
// Allow four spill batches, 8 MB each, plus one output of 16
// Allow for internal fragmentation
// 96 > (4 * 8 + 16) * 2
long memoryLimit = 96 * ONE_MEG;
SortMemoryManager memManager = new SortMemoryManager(sortConfig, memoryLimit);
// Prime the estimates. Batch size is data size, not buffer size.
int rowWidth = 300;
int rowCount = 10000;
int batchSize = rowWidth * rowCount * 2;
memManager.updateEstimates(batchSize, rowWidth, rowCount);
assertFalse(memManager.isLowMemory());
int spillBatchBufferSize = memManager.getSpillBatchSize().maxBufferSize;
int inputBatchBufferSize = memManager.getInputBatchSize().expectedBufferSize;
// One in-mem batch, no merging.
long allocMemory = inputBatchBufferSize;
MergeTask task = memManager.consolidateBatches(allocMemory, 1, 0);
assertEquals(MergeAction.NONE, task.action);
// Many in-mem batches, just enough to merge
int memBatches = (int) (memManager.getMergeMemoryLimit() / inputBatchBufferSize);
allocMemory = memBatches * inputBatchBufferSize;
task = memManager.consolidateBatches(allocMemory, memBatches, 0);
assertEquals(MergeAction.NONE, task.action);
// Spills if no room to merge spilled and in-memory batches
int spillCount = (int) Math.ceil((memManager.getMergeMemoryLimit() - allocMemory) / (1.0 * spillBatchBufferSize));
assertTrue(spillCount >= 1);
task = memManager.consolidateBatches(allocMemory, memBatches, spillCount);
assertEquals(MergeAction.SPILL, task.action);
// One more in-mem batch: now needs to spill
memBatches++;
allocMemory = memBatches * inputBatchBufferSize;
task = memManager.consolidateBatches(allocMemory, memBatches, 0);
assertEquals(MergeAction.SPILL, task.action);
// No spill for various in-mem/spill run combinations
long freeMem = memManager.getMergeMemoryLimit() - spillBatchBufferSize;
memBatches = (int) (freeMem / inputBatchBufferSize);
allocMemory = memBatches * inputBatchBufferSize;
task = memManager.consolidateBatches(allocMemory, memBatches, 1);
assertEquals(MergeAction.NONE, task.action);
freeMem = memManager.getMergeMemoryLimit() - 2 * spillBatchBufferSize;
memBatches = (int) (freeMem / inputBatchBufferSize);
allocMemory = memBatches * inputBatchBufferSize;
task = memManager.consolidateBatches(allocMemory, memBatches, 2);
assertEquals(MergeAction.NONE, task.action);
// No spill if no in-memory, only spill, and spill fits
freeMem = memManager.getMergeMemoryLimit();
int spillBatches = (int) (freeMem / spillBatchBufferSize);
task = memManager.consolidateBatches(0, 0, spillBatches);
assertEquals(MergeAction.NONE, task.action);
// One more and must merge
task = memManager.consolidateBatches(0, 0, spillBatches + 1);
assertEquals(MergeAction.MERGE, task.action);
assertEquals(2, task.count);
// Two more and will merge more
task = memManager.consolidateBatches(0, 0, spillBatches + 2);
assertEquals(MergeAction.MERGE, task.action);
assertEquals(3, task.count);
// If only one spilled run, and no in-memory batches,
// skip merge.
task = memManager.consolidateBatches(0, 0, 1);
assertEquals(MergeAction.NONE, task.action);
// Very large number of spilled runs. Limit to what fits in memory.
task = memManager.consolidateBatches(0, 0, 1000);
assertEquals(MergeAction.MERGE, task.action);
assertTrue(task.count <= (int) (memoryLimit / spillBatchBufferSize) - 1);
}
Aggregations