Class PoolChunk<T>

java.lang.Object
io.netty.buffer.PoolChunk<T>
All Implemented Interfaces:
PoolChunkMetric

final class PoolChunk<T> extends Object implements PoolChunkMetric
Description of algorithm for PageRun/PoolSubpage allocation from PoolChunk Notation: The following terms are important to understand the code > page - a page is the smallest unit of memory chunk that can be allocated > run - a run is a collection of pages > chunk - a chunk is a collection of runs > in this code chunkSize = maxPages * pageSize To begin we allocate a byte array of size = chunkSize Whenever a ByteBuf of given size needs to be created we search for the first position in the byte array that has enough empty space to accommodate the requested size and return a (long) handle that encodes this offset information, (this memory segment is then marked as reserved so it is always used by exactly one ByteBuf and no more) For simplicity all sizes are normalized according to
invalid @link
{@link PoolArena#sizeClass#size2SizeIdx(int)
} method. This ensures that when we request for memory segments of size > pageSize the normalizedCapacity equals the next nearest size in SizeClasses. A chunk has the following layout: /-----------------\ | run | | | | | |-----------------| | run | | | |-----------------| | unalloctated | | (freed) | | | |-----------------| | subpage | |-----------------| | unallocated | | (freed) | | ... | | ... | | ... | | | | | | | \-----------------/ handle: ------- a handle is a long number, the bit layout of a run looks like: oooooooo ooooooos ssssssss ssssssue bbbbbbbb bbbbbbbb bbbbbbbb bbbbbbbb o: runOffset (page offset in the chunk), 15bit s: size (number of pages) of this run, 15bit u: isUsed?, 1bit e: isSubpage?, 1bit b: bitmapIdx of subpage, zero if it's not subpage, 32bit runsAvailMap: ------ a map which manages all runs (used and not in used). For each run, the first runOffset and last runOffset are stored in runsAvailMap. key: runOffset value: handle runsAvail: ---------- an array of PriorityQueue. Each queue manages same size of runs. Runs are sorted by offset, so that we always allocate runs with smaller offset. Algorithm: ---------- As we allocate runs, we update values stored in runsAvailMap and runsAvail so that the property is maintained. Initialization - In the beginning we store the initial run which is the whole chunk. The initial run: runOffset = 0 size = chunkSize isUsed = no isSubpage = no bitmapIdx = 0 Algorithm: [allocateRun(size)] ---------- 1) find the first avail run using in runsAvails according to size 2) if pages of run is larger than request pages then split it, and save the tailing run for later using Algorithm: [allocateSubpage(size)] ---------- 1) find a not full subpage according to size. if it already exists just return, otherwise allocate a new PoolSubpage and call init() note that this subpage object is added to subpagesPool in the PoolArena when we init() it 2) call subpage.allocate() Algorithm: [free(handle, length, nioBuffer)] ---------- 1) if it is a subpage, return the slab back into this subpage 2) if the subpage is not used or it is a run, then start free this run 3) merge continuous avail runs 4) save the merged run
  • Field Details

    • SIZE_BIT_LENGTH

      private static final int SIZE_BIT_LENGTH
      See Also:
    • INUSED_BIT_LENGTH

      private static final int INUSED_BIT_LENGTH
      See Also:
    • SUBPAGE_BIT_LENGTH

      private static final int SUBPAGE_BIT_LENGTH
      See Also:
    • BITMAP_IDX_BIT_LENGTH

      private static final int BITMAP_IDX_BIT_LENGTH
      See Also:
    • IS_SUBPAGE_SHIFT

      static final int IS_SUBPAGE_SHIFT
      See Also:
    • IS_USED_SHIFT

      static final int IS_USED_SHIFT
      See Also:
    • SIZE_SHIFT

      static final int SIZE_SHIFT
      See Also:
    • RUN_OFFSET_SHIFT

      static final int RUN_OFFSET_SHIFT
      See Also:
    • arena

      final PoolArena<T> arena
    • base

      final Object base
    • memory

      final T memory
    • unpooled

      final boolean unpooled
    • runsAvailMap

      private final LongLongHashMap runsAvailMap
      store the first page and last page of each avail run
    • runsAvail

      private final IntPriorityQueue[] runsAvail
      manage all avail runs
    • runsAvailLock

      private final ReentrantLock runsAvailLock
    • subpages

      private final PoolSubpage<T>[] subpages
      manage all subpages in this chunk
    • pinnedBytes

      private final LongCounter pinnedBytes
      Accounting of pinned memory – memory that is currently in use by ByteBuf instances.
    • pageSize

      final int pageSize
    • pageShifts

      final int pageShifts
    • chunkSize

      final int chunkSize
    • maxPageIdx

      final int maxPageIdx
    • cachedNioBuffers

      private final Deque<ByteBuffer> cachedNioBuffers
    • freeBytes

      int freeBytes
    • parent

      PoolChunkList<T> parent
    • prev

      PoolChunk<T> prev
    • next

      PoolChunk<T> next
  • Constructor Details

    • PoolChunk

      PoolChunk(PoolArena<T> arena, Object base, T memory, int pageSize, int pageShifts, int chunkSize, int maxPageIdx)
    • PoolChunk

      PoolChunk(PoolArena<T> arena, Object base, T memory, int size)
      Creates a special chunk that is not pooled.
  • Method Details

    • newRunsAvailqueueArray

      private static IntPriorityQueue[] newRunsAvailqueueArray(int size)
    • insertAvailRun

      private void insertAvailRun(int runOffset, int pages, long handle)
    • insertAvailRun0

      private void insertAvailRun0(int runOffset, long handle)
    • removeAvailRun

      private void removeAvailRun(long handle)
    • removeAvailRun0

      private void removeAvailRun0(long handle)
    • lastPage

      private static int lastPage(int runOffset, int pages)
    • getAvailRunByOffset

      private long getAvailRunByOffset(int runOffset)
    • usage

      public int usage()
      Description copied from interface: PoolChunkMetric
      Return the percentage of the current usage of the chunk.
      Specified by:
      usage in interface PoolChunkMetric
    • usage

      private int usage(int freeBytes)
    • allocate

      boolean allocate(PooledByteBuf<T> buf, int reqCapacity, int sizeIdx, PoolThreadCache cache)
    • allocateRun

      private long allocateRun(int runSize)
    • calculateRunSize

      private int calculateRunSize(int sizeIdx)
    • runFirstBestFit

      private int runFirstBestFit(int pageIdx)
    • splitLargeRun

      private long splitLargeRun(long handle, int needPages)
    • allocateSubpage

      private long allocateSubpage(int sizeIdx, PoolSubpage<T> head)
      Create / initialize a new PoolSubpage of normCapacity. Any PoolSubpage created / initialized here is added to subpage pool in the PoolArena that owns this PoolChunk.
      Parameters:
      sizeIdx - sizeIdx of normalized size
      head - head of subpages
      Returns:
      index in memoryMap
    • free

      void free(long handle, int normCapacity, ByteBuffer nioBuffer)
      Free a subpage or a run of pages When a subpage is freed from PoolSubpage, it might be added back to subpage pool of the owning PoolArena. If the subpage pool in PoolArena has at least one other PoolSubpage of given elemSize, we can completely free the owning Page so it is available for subsequent allocations
      Parameters:
      handle - handle to free
    • collapseRuns

      private long collapseRuns(long handle)
    • collapsePast

      private long collapsePast(long handle)
    • collapseNext

      private long collapseNext(long handle)
    • toRunHandle

      private static long toRunHandle(int runOffset, int runPages, int inUsed)
    • initBuf

      void initBuf(PooledByteBuf<T> buf, ByteBuffer nioBuffer, long handle, int reqCapacity, PoolThreadCache threadCache)
    • initBufWithSubpage

      void initBufWithSubpage(PooledByteBuf<T> buf, ByteBuffer nioBuffer, long handle, int reqCapacity, PoolThreadCache threadCache)
    • incrementPinnedMemory

      void incrementPinnedMemory(int delta)
    • decrementPinnedMemory

      void decrementPinnedMemory(int delta)
    • chunkSize

      public int chunkSize()
      Description copied from interface: PoolChunkMetric
      Return the size of the chunk in bytes, this is the maximum of bytes that can be served out of the chunk.
      Specified by:
      chunkSize in interface PoolChunkMetric
    • freeBytes

      public int freeBytes()
      Description copied from interface: PoolChunkMetric
      Return the number of free bytes in the chunk.
      Specified by:
      freeBytes in interface PoolChunkMetric
    • pinnedBytes

      public int pinnedBytes()
    • toString

      public String toString()
      Overrides:
      toString in class Object
    • destroy

      void destroy()
    • runOffset

      static int runOffset(long handle)
    • runSize

      static int runSize(int pageShifts, long handle)
    • runPages

      static int runPages(long handle)
    • isUsed

      static boolean isUsed(long handle)
    • isRun

      static boolean isRun(long handle)
    • isSubpage

      static boolean isSubpage(long handle)
    • bitmapIdx

      static int bitmapIdx(long handle)