Package io.netty.buffer
Class PoolChunk<T>
java.lang.Object
io.netty.buffer.PoolChunk<T>
- All Implemented Interfaces:
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
} method.
This ensures that when we request for memory segments of size > pageSize the normalizedCapacity
equals the next nearest size in
invalid @link
{@link PoolArena#sizeClass#size2SizeIdx(int)
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 Summary
FieldsModifier and TypeFieldDescription(package private) final Object
private static final int
private final Deque
<ByteBuffer> private final int
(package private) int
private static final int
(package private) static final int
(package private) static final int
(package private) final T
private final int
private final int
(package private) PoolChunkList
<T> private final LongCounter
Accounting of pinned memory – memory that is currently in use by ByteBuf instances.(package private) static final int
private final IntPriorityQueue[]
manage all avail runsprivate final ReentrantLock
private final LongLongHashMap
store the first page and last page of each avail runprivate static final int
(package private) static final int
private static final int
private final PoolSubpage<T>[]
manage all subpages in this chunk(package private) final boolean
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescription(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
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, 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
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, ByteBuffer nioBuffer, long handle, int reqCapacity, PoolThreadCache threadCache) (package private) void
initBufWithSubpage
(PooledByteBuf<T> buf, 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
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) toString()
int
usage()
Return the percentage of the current usage of the chunk.private int
usage
(int freeBytes)
-
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
-
base
-
memory
-
unpooled
final boolean unpooled -
runsAvailMap
store the first page and last page of each avail run -
runsAvail
manage all avail runs -
runsAvailLock
-
subpages
manage all subpages in this chunk -
pinnedBytes
Accounting of pinned memory – memory that is currently in use by ByteBuf instances. -
pageSize
private final int pageSize -
pageShifts
private final int pageShifts -
chunkSize
private final int chunkSize -
cachedNioBuffers
-
freeBytes
int freeBytes -
parent
PoolChunkList<T> parent -
prev
-
next
-
-
Constructor Details
-
PoolChunk
-
PoolChunk
Creates a special chunk that is not pooled.
-
-
Method Details
-
newRunsAvailqueueArray
-
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
-
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
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
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 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
-
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)
-