Package io.netty.buffer
Class PoolChunk<T>
- java.lang.Object
-
- io.netty.buffer.PoolChunk<T>
-
- All Implemented Interfaces:
PoolChunkMetric
final class PoolChunk<T> extends java.lang.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 {@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 inSizeClasses
. 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 ofPriorityQueue
. 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 Summary
Fields Modifier and Type Field Description (package private) PoolArena<T>
arena
(package private) java.lang.Object
base
private static int
BITMAP_IDX_BIT_LENGTH
private java.util.Deque<java.nio.ByteBuffer>
cachedNioBuffers
(package private) int
chunkSize
(package private) int
freeBytes
private static int
INUSED_BIT_LENGTH
(package private) static int
IS_SUBPAGE_SHIFT
(package private) static int
IS_USED_SHIFT
(package private) int
maxPageIdx
(package private) T
memory
(package private) PoolChunk<T>
next
(package private) int
pageShifts
(package private) int
pageSize
(package private) PoolChunkList<T>
parent
private LongCounter
pinnedBytes
Accounting of pinned memory – memory that is currently in use by ByteBuf instances.(package private) PoolChunk<T>
prev
(package private) static int
RUN_OFFSET_SHIFT
private IntPriorityQueue[]
runsAvail
manage all avail runsprivate java.util.concurrent.locks.ReentrantLock
runsAvailLock
private LongLongHashMap
runsAvailMap
store the first page and last page of each avail runprivate static int
SIZE_BIT_LENGTH
(package private) static int
SIZE_SHIFT
private static int
SUBPAGE_BIT_LENGTH
private PoolSubpage<T>[]
subpages
manage all subpages in this chunk(package private) boolean
unpooled
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description (package private) boolean
allocate(PooledByteBuf<T> buf, int reqCapacity, int sizeIdx, PoolThreadCache cache)
private long
allocateRun(int runSize)
private long
allocateSubpage(int sizeIdx, PoolSubpage<T> head)
Create / initialize a new PoolSubpage of normCapacity.(package private) static int
bitmapIdx(long handle)
private int
calculateRunSize(int sizeIdx)
int
chunkSize()
Return the size of the chunk in bytes, this is the maximum of bytes that can be served out of the chunk.private long
collapseNext(long handle)
private long
collapsePast(long handle)
private long
collapseRuns(long handle)
(package private) void
decrementPinnedMemory(int delta)
(package private) void
destroy()
(package private) void
free(long handle, int normCapacity, java.nio.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.int
freeBytes()
Return the number of free bytes in the chunk.private long
getAvailRunByOffset(int runOffset)
(package private) void
incrementPinnedMemory(int delta)
(package private) void
initBuf(PooledByteBuf<T> buf, java.nio.ByteBuffer nioBuffer, long handle, int reqCapacity, PoolThreadCache threadCache)
(package private) void
initBufWithSubpage(PooledByteBuf<T> buf, java.nio.ByteBuffer nioBuffer, long handle, int reqCapacity, PoolThreadCache threadCache)
private void
insertAvailRun(int runOffset, int pages, long handle)
private void
insertAvailRun0(int runOffset, long handle)
(package private) static boolean
isRun(long handle)
(package private) static boolean
isSubpage(long handle)
(package private) static boolean
isUsed(long handle)
private static int
lastPage(int runOffset, int pages)
private static IntPriorityQueue[]
newRunsAvailqueueArray(int size)
int
pinnedBytes()
private void
removeAvailRun(long handle)
private void
removeAvailRun0(long handle)
private int
runFirstBestFit(int pageIdx)
(package private) static int
runOffset(long handle)
(package private) static int
runPages(long handle)
(package private) static int
runSize(int pageShifts, long handle)
private long
splitLargeRun(long handle, int needPages)
private static long
toRunHandle(int runOffset, int runPages, int inUsed)
java.lang.String
toString()
int
usage()
Return the percentage of the current usage of the chunk.private int
usage(int freeBytes)
-
-
-
Field Detail
-
SIZE_BIT_LENGTH
private static final int SIZE_BIT_LENGTH
- See Also:
- Constant Field Values
-
INUSED_BIT_LENGTH
private static final int INUSED_BIT_LENGTH
- See Also:
- Constant Field Values
-
SUBPAGE_BIT_LENGTH
private static final int SUBPAGE_BIT_LENGTH
- See Also:
- Constant Field Values
-
BITMAP_IDX_BIT_LENGTH
private static final int BITMAP_IDX_BIT_LENGTH
- See Also:
- Constant Field Values
-
IS_SUBPAGE_SHIFT
static final int IS_SUBPAGE_SHIFT
- See Also:
- Constant Field Values
-
IS_USED_SHIFT
static final int IS_USED_SHIFT
- See Also:
- Constant Field Values
-
SIZE_SHIFT
static final int SIZE_SHIFT
- See Also:
- Constant Field Values
-
RUN_OFFSET_SHIFT
static final int RUN_OFFSET_SHIFT
- See Also:
- Constant Field Values
-
base
final java.lang.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 java.util.concurrent.locks.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 java.util.Deque<java.nio.ByteBuffer> cachedNioBuffers
-
freeBytes
int freeBytes
-
parent
PoolChunkList<T> parent
-
-
Method Detail
-
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 interfacePoolChunkMetric
-
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 sizehead
- head of subpages- Returns:
- index in memoryMap
-
free
void free(long handle, int normCapacity, java.nio.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, java.nio.ByteBuffer nioBuffer, long handle, int reqCapacity, PoolThreadCache threadCache)
-
initBufWithSubpage
void initBufWithSubpage(PooledByteBuf<T> buf, java.nio.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 interfacePoolChunkMetric
-
freeBytes
public int freeBytes()
Description copied from interface:PoolChunkMetric
Return the number of free bytes in the chunk.- Specified by:
freeBytes
in interfacePoolChunkMetric
-
pinnedBytes
public int pinnedBytes()
-
toString
public java.lang.String toString()
- Overrides:
toString
in classjava.lang.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)
-
-