Return-Path: X-Original-To: apmail-drill-issues-archive@minotaur.apache.org Delivered-To: apmail-drill-issues-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 29EEA18E74 for ; Tue, 1 Dec 2015 18:24:27 +0000 (UTC) Received: (qmail 93802 invoked by uid 500); 1 Dec 2015 18:24:11 -0000 Delivered-To: apmail-drill-issues-archive@drill.apache.org Received: (qmail 93738 invoked by uid 500); 1 Dec 2015 18:24:11 -0000 Mailing-List: contact issues-help@drill.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@drill.apache.org Delivered-To: mailing list issues@drill.apache.org Received: (qmail 93705 invoked by uid 99); 1 Dec 2015 18:24:11 -0000 Received: from arcas.apache.org (HELO arcas) (140.211.11.28) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 01 Dec 2015 18:24:11 +0000 Received: from arcas.apache.org (localhost [127.0.0.1]) by arcas (Postfix) with ESMTP id 159F82C1F6E for ; Tue, 1 Dec 2015 18:24:11 +0000 (UTC) Date: Tue, 1 Dec 2015 18:24:11 +0000 (UTC) From: "ASF GitHub Bot (JIRA)" To: issues@drill.apache.org Message-ID: In-Reply-To: References: Subject: [jira] [Commented] (DRILL-4134) Incorporate remaining patches from DRILL-1942 Allocator refactor MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-JIRA-FingerPrint: 30527f35849b9dde25b450d4833f0394 [ https://issues.apache.org/jira/browse/DRILL-4134?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15034271#comment-15034271 ] ASF GitHub Bot commented on DRILL-4134: --------------------------------------- Github user julienledem commented on a diff in the pull request: https://github.com/apache/drill/pull/283#discussion_r46316597 --- Diff: exec/memory/base/src/main/java/org/apache/drill/exec/memory/README.md --- @@ -0,0 +1,121 @@ + +# Memory: Allocation, Accounting and Management + +The memory management package contains all the memory allocation related items that Drill uses to manage memory. + + +## Key Components +Memory management can be broken into the following main components: + +- Memory chunk allocation and fragmentation management + - `PooledByteBufAllocatorL` - A LittleEndian clone of Netty's jemalloc implementation + - `UnsafeDirectLittleEndian` - A base level memory access interface + - `LargeBuffer` - A buffer backing implmentation used when working with data larger than one Netty chunk (default to 16mb) +- Memory limits & Accounting + - `Accountant` - A nestable class of lockfree memory accountors. +- Application-level memory allocation + - `BufferAllocator` - The public interface application users should be leveraging + - `BaseAllocator` - The base implementation of memory allocation, contains the meat of our the Drill allocator implementation + - `RootAllocator` - The root allocator. Typically only one created for a JVM + - `ChildAllocator` - A child allocator that derives from the root allocator +- Buffer ownership and transfer capabilities + - `AllocatorManager` - Responsible for managing the relationship between multiple allocators and a single chunk of memory + - `BufferLedger` - Responsible for allowing maintaining the relationship between an `AllocatorManager`, a `BufferAllocator` and one or more individual `DrillBuf`s +- Memory access + - `DrillBuf` - The facade for interacting directly with a chunk of memory. + + +## Memory Management Overview +Drill's memory model is based on the following basic concepts: + + - Memory can be allocated up to some limit. That limit could be a real limit (OS/JVM) or a locally imposed limit. + - Allocation operates in two phases: accounting then actual allocation. Allocation could fail at either point. + - Allocation failure should be recoverable. In all cases, the Allocator infrastructure should expose memory allocation failures (OS or internal limit-based) as `OutOfMemoryException`s. + - Any allocator can reserve memory when created. This memory shall be held such that this allocator will always be able to allocate that amount of memory. + - A particular application component should work to use a local allocator to understand local memory usage and better debug memory leaks. + - The same physical memory can be shared by multiple allocators and the allocator must provide an accounting paradigm for this purpose. + +## Allocator Trees + +Drill provides a tree-based model for memory allocation. The RootAllocator is created first, then all allocators are created as children of that allocator. The RootAllocator is responsible for being the master bookeeper for memory allocations. All other allocators are created as children of this tree. Each allocator can first determine whether it has enough local memory to satisfy a particular request. If not, the allocator can ask its parent for an additional memory allocation. + +## Reserving Memory + +Drill provides two different ways to reserve memory: + + - BufferAllocator accounting reservations: + When a new allocator (other than the `RootAllocator`) is initialized, it can set aside memory that it will keep locally for its lifetime. This is memory that will never be released back to its parent allocator until the allocator + - `AllocationReservation` via BufferAllocator.newReservation(): Allows a short-term preallocation strategy so that a particular subsystem can ensure future memory is available to support a particular request. + +## Memory Ownership, Reference Counts and Sharing +Many BufferAllocators can reference the same piece of memory at the same time. The most common situation for this is in the case of a Broadcast Join: in this situation many downstream operators in the same Drillbit will receive the same physical memory. Each of these operators will be operating within its own Allocator context. We therefore have multiple allocators all pointing at the same physical memory. It is the AllocatorManager's responsibility to ensure that in this situation, that all memory is accurately accounted for from the Root's perspective and also to ensure that the memory is correctly released once all BufferAllocators have stopped using that memory. + +For simplicity of accounting, we treat that memory as being used by one of the BufferAllocators associated with the memory. When that allocator releases its claim on that memory, the memory ownership is then moved to another BufferLedger belonging to the same AllocatorManager. Note that because a DrillBuf.release() is what actually causes memory ownership transfer to occur, we always precede with ownership transfer (even if that violates an allocator limit). It is the responsibility of the application owning a particular allocator to frequently confirm whether the allocator is over its memory limit (BufferAllocator.isOverLimit()) and if so, attempt to aggresively release memory to ameliorate the situation. + +All DrillBufs (direct or sliced) related to a single BufferLedger/BufferAllocator combination share the same reference count and either all will be valid or all will be invalid. + +## Object Hierarchy + +There are two main ways that someone can look at the object hierarchy for Drill's memory management scheme. The first is a memory based perspective as below: + +### Memory Perspective +
    ++ AllocatorManager
    +|
    +|-- UnsignedDirectLittleEndian (One per AllocatorManager)
    +|
    +|-+ BufferLedger 1 ==> Allocator A (owning)
    +| ` - DrillBuf 1
    +|-+ BufferLedger 2 ==> Allocator B (non-owning)
    +| ` - DrillBuf 2
    +|-+ BufferLedger 3 ==> Allocator C (non-owning)
    +  | - DrillBuf 3
    +  | - DrillBuf 4
    +  ` - DrillBuf 5
    +
+ +In this picture, a piece of memory is owned by an allocator manager. An allocator manager is responsible for that piece of memory no matter which allocator(s) it is working with. An allocator manager will have relationships with a piece of raw memory (via its reference to UnsignedDirectLittleEndian) as well as references to each BufferAllocator it has a relationship to. When understanding the + --- End diff -- when understanding the ... ? > Incorporate remaining patches from DRILL-1942 Allocator refactor > ---------------------------------------------------------------- > > Key: DRILL-4134 > URL: https://issues.apache.org/jira/browse/DRILL-4134 > Project: Apache Drill > Issue Type: Sub-task > Components: Execution - Flow > Reporter: Jacques Nadeau > Assignee: Jacques Nadeau > Fix For: 1.4.0 > > -- This message was sent by Atlassian JIRA (v6.3.4#6332)