[
https://issues.apache.org/jira/browse/DRILL-1942?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14286632#comment-14286632
]
Chris Westin commented on DRILL-1942:
-------------------------------------
Simplify memory allocators
(*) Remove unused fields from ChildAllocator and TopLevelAllocator.
Eclipse reports several unused fields.
(*) Extract ChildAllocator class from TopLevelAllocator
Currently, ChildAllocator is a nested class inside TopLevelAllocator. It should
instead be a separate class.
As part of this process, merge the Accountor class with the allocator classes.
There should be a base allocator class that knows how to do accounting, and the
(new) RootAllocator and ChildAllocator classes should derive from this common
base class. This shouldn't be difficult, because it currently looks like there
aren't any references to any of TopLevelAllocator's fields in ChildAllocator.
Since ChildAllocator can also spawn more child allocators, and these should be
children of the child, not of the same parent, extracting ChildAllocator in
this way will help maintain a strict hierarchy if that should happen.
Allocators can be thought of as Scopes, and should observe nesting similar to
nested block scoping in programming language environments.
(*) Improve memory usage tracking
We're using too much memory, but we don't know where or why. Allocators provide
an excellent way to track this, if we can rely on them to track memory usage
more finely than we currently do.
Make sure that we are using the allocator instance hierarchy that results from
the above restructuring of the allocators properly for accounting. If an
allocator runs out of memory, and needs more, it should request it from it's
parent. If an allocator is done with memory, it should be returned to its
parent. Do not short-circuit the accounting mechanisms (as is done now) by
directly walking up the allocator instance hierarchy and adjusting accounting
directly. Allow each allocator to make its own adjustments as memory is
returned to it. Each allocator instance should be encapsulated properly, with
the only currency passing between them being memory, and that being done
through their published interface.
Allocator ownership is currently associated with a FragmentContext. But we'd
like to know which operators are using memory, and how much of it. This can be
done by making sure that each operator has its own allocator. Use of child
allocators makes this easy. However, we need more than the FragmentContext;
each allocator needs to know what operator it is associated with, so
getChildAllocator() may need more arguments.
We want to be able to track it per operator per query.
In order to access this information, we've decided that for now, we want to
make it available via JMX, as well as providing an option to dump it to the log
at the end of the query.
(*) Take advantage of the allocator instance hierarchy for cleanup While we
should continue to do strict accounting similar to that done now
(activated by enabling Java assertions), we should take advantage of the
resulting allocator instance hierarchy for cleanup purposes. In the event that
we do have bugs that lead to buffers from intermediate child allocators not
being freed, or if intermediate allocators themselves are not freed, we can do
that implicitly when an ancestral allocator is freed.
Building on the above, if we close() an allocator, all of the memory belonging
to it and all of its descendants is freed. This should be done from the bottom
up: all memory belonging to the leafmost allocators is reclaimed first, and
their allocators are closed, and so on up the tree up to and including the
allocator that was directly close()d.
We expect to catch bugs in code that doesn't follow this protocol by running
tests with assertions, but if we do have bugs we still don't want to have
leaks; following this protocol will assure that.
(*) Cope with memory sharing between operators
It looks like there are times when DrillBufs are passed between operators
wholesale in order to pass data without copying. This requires the ability to
exchange ownership between allocators. This ability currently exists, but needs
to be modified a bit to fit all of the above.
In addition to that, DrillBufs are sometimes shared in the above scenario: for
a hash or partitioning exchange, some data in one buffer may be sent to one
operator, and other data in the same buffer may need to be sent to a different
operator. When this happens, the buffer is shared by both operators. We don't
appear to have good accounting for this at this time. We need to introduce the
reference counting mechanism to support this, and only account for the used
memory once.
We've speculated that there may also be situations where we need to share an
allocator between multiple operators (or other agents), and that we may need to
support reference counting for allocators themselves, but this is not certain.
If so, we may need to provide a means to wrap them with an allocator whose
implementation delegates most calls, but whose close() decrements a reference
count and only closes the real allocator on the last close().
> Improve off-heap memory usage tracking
> --------------------------------------
>
> Key: DRILL-1942
> URL: https://issues.apache.org/jira/browse/DRILL-1942
> Project: Apache Drill
> Issue Type: Improvement
> Components: Execution - Operators
> Reporter: Chris Westin
> Assignee: Chris Westin
>
> We're using a lot more memory than we think we should. We may be leaking it,
> or not releasing it as soon as we could.
> This is a call to come up with some improved tracking so that we can get
> statistics out about exactly where we're using it, and whether or not we can
> release it earlier.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)