You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@drill.apache.org by "Deneche A. Hakim (JIRA)" <ji...@apache.org> on 2015/11/18 20:44:11 UTC

[jira] [Commented] (DRILL-4112) BaseDataValueVector.getBuffers(false) doesn't return it's inner buffer which affects transfer of ownership between allocators in ExternalSort

    [ https://issues.apache.org/jira/browse/DRILL-4112?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15011792#comment-15011792 ] 

Deneche A. Hakim commented on DRILL-4112:
-----------------------------------------

a quick note here, the unit test is incomplete because we don't clear the allocated vector, but this doesn't change the original issue

> BaseDataValueVector.getBuffers(false) doesn't return it's inner buffer which affects transfer of ownership between allocators in ExternalSort
> ---------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: DRILL-4112
>                 URL: https://issues.apache.org/jira/browse/DRILL-4112
>             Project: Apache Drill
>          Issue Type: Bug
>    Affects Versions: 1.2.0
>            Reporter: Deneche A. Hakim
>
> As part of fixing DRILL-2274, to avoid running out of memory in sort when it spilled to disk we close the _copierAllocator_ after we receive the last batch from upstream, this way it releases all it's allocated memory back to it's parent allocator. The assumption is that the _copierAllocator_ doesn't own any buffers once a _mergeAndSpill_ is done and we no longer need it if we are no longer
> spilling to disk.
> This causes it's accountor to complain that some buffers weren't closed (when assertions are enabled), which goes against the previous assumption.
> The _copierAllocator_ is used to allocate many batches while spilling but only one is kept in memory and the following method transfers it's ownership to the operator's allocator:
> {code}
>   private void takeOwnership(VectorAccessible batch) {
>     for (VectorWrapper<?> w : batch) {
>       DrillBuf[] bufs = w.getValueVector().getBuffers(false);
>       for (DrillBuf buf : bufs) {
>         if (buf.isRootBuffer()) {
>           oContext.getAllocator().takeOwnership(buf);
>         }
>       }
>     }
>   }
> {code}
> The problem comes from how _BaseDataValueVector.getBuffers(boolean clear)_ is implemented:
> {code}
>   @Override
>   public DrillBuf[] getBuffers(boolean clear) {
>     DrillBuf[] out;
>     if (getBufferSize() == 0) {
>       out = new DrillBuf[0];
>     } else {
>       out = new DrillBuf[]{data};
>       if (clear) {
>         data.readerIndex(0);
>         data.retain(1);
>       }
>     }
>     if (clear) {
>       clear();
>     }
>     return out;
>   }
> {code}
> If we don't write any value into the vector, and call _getBuffers(false)_, it won't return it's allocated buffer but an empty array instead. Thus, the buffer won't be transferred to the operator's allocator.
> The following unit test will exposes the problem:
> {code}
>   @Test
>   public void testTakeOwnership() throws Exception {
>     final MaterializedField field = MaterializedField.create(SchemaPath.getSimplePath(""), NullableVarCharHolder.TYPE);
>     final DrillConfig drillConfig = DrillConfig.create();
>     final BufferAllocator allocator = RootAllocatorFactory.newRoot(drillConfig);
>     final BufferAllocator childAllocator = allocator.getChildAllocator(null, 10000, 20000, false);
>     final NullableVarCharVector vector = new NullableVarCharVector(field, childAllocator);
>     vector.allocateNew(1024 * 10, 1024);
>     DrillBuf[] buffers = vector.getBuffers(false);
>     for (final DrillBuf buffer : buffers) {
>       allocator.takeOwnership(buffer);
>     }
>     childAllocator.close();
>     allocator.close();
>   }
> {code}
> When closing _childAllocator_ we get the following exception (when assertions are enabled):
> {noformat}
> java.lang.IllegalStateException: Attempted to close accountor with 3 buffer(s) still allocated.
> 	Total 1 allocation(s) of byte size(s): 4100, at stack location:
> 		org.apache.drill.exec.memory.TopLevelAllocator$ChildAllocator.buffer(TopLevelAllocator.java:256)
> 		org.apache.drill.exec.vector.UInt4Vector.allocateBytes(UInt4Vector.java:209)
> 		org.apache.drill.exec.vector.UInt4Vector.allocateNew(UInt4Vector.java:191)
> 		org.apache.drill.exec.vector.VarCharVector.allocateNew(VarCharVector.java:386)
> 		org.apache.drill.exec.vector.NullableVarCharVector.allocateNew(NullableVarCharVector.java:224)
> 		org.apache.drill.exec.record.vector.TestValueVector.testTakeOwnership(TestValueVector.java:123)
> 		sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> 		sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
> 		sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> 		java.lang.reflect.Method.invoke(Method.java:606)
> 		org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
> 		org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
> 		org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
> 		mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.executeTestMethod(JUnit4TestRunnerDecorator.java:120)
> 		mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.invokeExplosively(JUnit4TestRunnerDecorator.java:65)
> 		mockit.integration.junit4.internal.MockFrameworkMethod.invokeExplosively(MockFrameworkMethod.java:29)
> 		sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> 		sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
> 		sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> 		java.lang.reflect.Method.invoke(Method.java:606)
> 		mockit.internal.util.MethodReflection.invokeWithCheckedThrows(MethodReflection.java:95)
> 		mockit.internal.annotations.MockMethodBridge.callMock(MockMethodBridge.java:76)
> 		mockit.internal.annotations.MockMethodBridge.invoke(MockMethodBridge.java:41)
> 		org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java)
> 		org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
> 		org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
> 		org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
> 		org.junit.internal.runners.statements.FailOnTimeout$StatementThread.run(FailOnTimeout.java:74)
> 	Total 1 allocation(s) of byte size(s): 1024, at stack location:
> 		org.apache.drill.exec.memory.TopLevelAllocator$ChildAllocator.buffer(TopLevelAllocator.java:256)
> 		org.apache.drill.exec.vector.UInt1Vector.allocateBytes(UInt1Vector.java:209)
> 		org.apache.drill.exec.vector.UInt1Vector.allocateNew(UInt1Vector.java:191)
> 		org.apache.drill.exec.vector.NullableVarCharVector.allocateNew(NullableVarCharVector.java:225)
> 		org.apache.drill.exec.record.vector.TestValueVector.testTakeOwnership(TestValueVector.java:123)
> 		sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> 		sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
> 		sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> 		java.lang.reflect.Method.invoke(Method.java:606)
> 		org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
> 		org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
> 		org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
> 		mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.executeTestMethod(JUnit4TestRunnerDecorator.java:120)
> 		mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.invokeExplosively(JUnit4TestRunnerDecorator.java:65)
> 		mockit.integration.junit4.internal.MockFrameworkMethod.invokeExplosively(MockFrameworkMethod.java:29)
> 		sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> 		sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
> 		sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> 		java.lang.reflect.Method.invoke(Method.java:606)
> 		mockit.internal.util.MethodReflection.invokeWithCheckedThrows(MethodReflection.java:95)
> 		mockit.internal.annotations.MockMethodBridge.callMock(MockMethodBridge.java:76)
> 		mockit.internal.annotations.MockMethodBridge.invoke(MockMethodBridge.java:41)
> 		org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java)
> 		org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
> 		org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
> 		org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
> 		org.junit.internal.runners.statements.FailOnTimeout$StatementThread.run(FailOnTimeout.java:74)
> 	Total 1 allocation(s) of byte size(s): 10240, at stack location:
> 		org.apache.drill.exec.memory.TopLevelAllocator$ChildAllocator.buffer(TopLevelAllocator.java:256)
> 		org.apache.drill.exec.vector.VarCharVector.allocateNew(VarCharVector.java:385)
> 		org.apache.drill.exec.vector.NullableVarCharVector.allocateNew(NullableVarCharVector.java:224)
> 		org.apache.drill.exec.record.vector.TestValueVector.testTakeOwnership(TestValueVector.java:123)
> 		sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> 		sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
> 		sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> 		java.lang.reflect.Method.invoke(Method.java:606)
> 		org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
> 		org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
> 		org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
> 		mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.executeTestMethod(JUnit4TestRunnerDecorator.java:120)
> 		mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.invokeExplosively(JUnit4TestRunnerDecorator.java:65)
> 		mockit.integration.junit4.internal.MockFrameworkMethod.invokeExplosively(MockFrameworkMethod.java:29)
> 		sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> 		sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
> 		sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> 		java.lang.reflect.Method.invoke(Method.java:606)
> 		mockit.internal.util.MethodReflection.invokeWithCheckedThrows(MethodReflection.java:95)
> 		mockit.internal.annotations.MockMethodBridge.callMock(MockMethodBridge.java:76)
> 		mockit.internal.annotations.MockMethodBridge.invoke(MockMethodBridge.java:41)
> 		org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java)
> 		org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
> 		org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
> 		org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
> 		org.junit.internal.runners.statements.FailOnTimeout$StatementThread.run(FailOnTimeout.java:74)
> java.lang.IllegalStateException: Attempted to close accountor with 3 buffer(s) still allocated.
> 	Total 1 allocation(s) of byte size(s): 4100, at stack location:
> 		org.apache.drill.exec.memory.TopLevelAllocator$ChildAllocator.buffer(TopLevelAllocator.java:256)
> 		org.apache.drill.exec.vector.UInt4Vector.allocateBytes(UInt4Vector.java:209)
> 		org.apache.drill.exec.vector.UInt4Vector.allocateNew(UInt4Vector.java:191)
> 		org.apache.drill.exec.vector.VarCharVector.allocateNew(VarCharVector.java:386)
> 		org.apache.drill.exec.vector.NullableVarCharVector.allocateNew(NullableVarCharVector.java:224)
> 		org.apache.drill.exec.record.vector.TestValueVector.testTakeOwnership(TestValueVector.java:123)
> 		sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> 		sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
> 		sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> 		org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
> 		org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
> 		org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
> 		mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.executeTestMethod(JUnit4TestRunnerDecorator.java:120)
> 		mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.invokeExplosively(JUnit4TestRunnerDecorator.java:65)
> 		mockit.integration.junit4.internal.MockFrameworkMethod.invokeExplosively(MockFrameworkMethod.java:29)
> 		sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> 		sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
> 		sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> 		mockit.internal.util.MethodReflection.invokeWithCheckedThrows(MethodReflection.java:95)
> 		mockit.internal.annotations.MockMethodBridge.callMock(MockMethodBridge.java:76)
> 		mockit.internal.annotations.MockMethodBridge.invoke(MockMethodBridge.java:41)
> 		org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java)
> 		org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
> 		org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
> 		org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
> 		org.junit.internal.runners.statements.FailOnTimeout$StatementThread.run(FailOnTimeout.java:74)
> 	Total 1 allocation(s) of byte size(s): 1024, at stack location:
> 		org.apache.drill.exec.memory.TopLevelAllocator$ChildAllocator.buffer(TopLevelAllocator.java:256)
> 		org.apache.drill.exec.vector.UInt1Vector.allocateBytes(UInt1Vector.java:209)
> 		org.apache.drill.exec.vector.UInt1Vector.allocateNew(UInt1Vector.java:191)
> 		org.apache.drill.exec.vector.NullableVarCharVector.allocateNew(NullableVarCharVector.java:225)
> 		org.apache.drill.exec.record.vector.TestValueVector.testTakeOwnership(TestValueVector.java:123)
> 		sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> 		sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
> 		sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> 		org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
> 		org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
> 		org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
> 		mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.executeTestMethod(JUnit4TestRunnerDecorator.java:120)
> 		mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.invokeExplosively(JUnit4TestRunnerDecorator.java:65)
> 		mockit.integration.junit4.internal.MockFrameworkMethod.invokeExplosively(MockFrameworkMethod.java:29)
> 		sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> 		sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
> 		sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> 		mockit.internal.util.MethodReflection.invokeWithCheckedThrows(MethodReflection.java:95)
> 		mockit.internal.annotations.MockMethodBridge.callMock(MockMethodBridge.java:76)
> 		mockit.internal.annotations.MockMethodBridge.invoke(MockMethodBridge.java:41)
> 		org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java)
> 		org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
> 		org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
> 		org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
> 		org.junit.internal.runners.statements.FailOnTimeout$StatementThread.run(FailOnTimeout.java:74)
> 	Total 1 allocation(s) of byte size(s): 10240, at stack location:
> 		org.apache.drill.exec.memory.TopLevelAllocator$ChildAllocator.buffer(TopLevelAllocator.java:256)
> 		org.apache.drill.exec.vector.VarCharVector.allocateNew(VarCharVector.java:385)
> 		org.apache.drill.exec.vector.NullableVarCharVector.allocateNew(NullableVarCharVector.java:224)
> 		org.apache.drill.exec.record.vector.TestValueVector.testTakeOwnership(TestValueVector.java:123)
> 		sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> 		sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
> 		sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> 		org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
> 		org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
> 		org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
> 		mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.executeTestMethod(JUnit4TestRunnerDecorator.java:120)
> 		mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.invokeExplosively(JUnit4TestRunnerDecorator.java:65)
> 		mockit.integration.junit4.internal.MockFrameworkMethod.invokeExplosively(MockFrameworkMethod.java:29)
> 		sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> 		sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
> 		sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> 		mockit.internal.util.MethodReflection.invokeWithCheckedThrows(MethodReflection.java:95)
> 		mockit.internal.annotations.MockMethodBridge.callMock(MockMethodBridge.java:76)
> 		mockit.internal.annotations.MockMethodBridge.invoke(MockMethodBridge.java:41)
> 		org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java)
> 		org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
> 		org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
> 		org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
> 		org.junit.internal.runners.statements.FailOnTimeout$StatementThread.run(FailOnTimeout.java:74)
> 	at org.apache.drill.exec.memory.Accountor.close(Accountor.java:381)
> 	at org.apache.drill.exec.memory.TopLevelAllocator$ChildAllocator.close(TopLevelAllocator.java:327)
> 	at org.apache.drill.exec.record.vector.TestValueVector.testTakeOwnership(TestValueVector.java:130)
> 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> {noformat}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)