Class AdaptivePoolingAllocator.ThreadLocalSizeClassedChunkCache
- java.lang.Object
-
- io.netty.buffer.AdaptivePoolingAllocator.SizeClassedChunkCache
-
- io.netty.buffer.AdaptivePoolingAllocator.ThreadLocalSizeClassedChunkCache
-
- All Implemented Interfaces:
AdaptivePoolingAllocator.ChunkCache
- Enclosing class:
- AdaptivePoolingAllocator
static final class AdaptivePoolingAllocator.ThreadLocalSizeClassedChunkCache extends AdaptivePoolingAllocator.SizeClassedChunkCache
Ring buffer cache for thread-local chunk reuse (SPSC — only the owner thread accesses it).Logical layout after purge:
head tail v v [..., notEmpty, notEmpty, ..., empty, empty, ..., null, ...] |--- notEmptyCount ---|--- emptyCount --| |------------ count ------------------|Physical layout when the ring wraps:
0 tail head length v v v v [...tail] [ unused ] [head................] ^ |--- content wraps ---| wrap pointscanForCapacity — O(1) fast path takes from head while
notEmptyCount > 0:before: notEmptyCount=2, count=5 [NE, NE, E, E, E, _, _, _] ^head ^tail after: returns NE, notEmptyCount=1, count=4 [_, NE, E, E, E, _, _, _] ^head ^tailFallback whennotEmptyCount == 0: linear scan of the empty zone for chunks that gained capacity from external segment returns.offerChunk — write at tail, grow (double + linearize) if full:
before: count=4 [_, NE, E, E, E, _, _, _] ^head ^tail after: count=5 [_, NE, E, E, E, X, _, _] ^head ^tailrunPurgeScan (every
AdaptivePoolingAllocator.CHUNK_PURGE_POLLS_THREAD_LOCALpolls) — two passes. Pass 1: age idle chunks (full → epoch++, non-full → epoch=0), evict past threshold, compact survivors (nulls stale slots inline). Pass 2: partition hasCap to front / noCap to back, then three-way Dutch-flag within hasCap into [epoch=0 | 0<epoch<threshold | epoch>=threshold]. Chunks with epoch>=threshold are placed at the back of hasCap so scan doesn't reach them — they age to threshold+1 and get evicted. Never selects — selection is alwaysscanForCapacity.Case 1 — no eviction, an empty chunk gained capacity externally (common):
before (E* gained capacity since last purge): [NE, NE, E*, E, _, _, _, _] ^head ^tail notEmptyCount=2 pass 1: age idle chunks. None past threshold. No compaction needed. pass 2 (partition): E* now has capacity → placed in notEmpty zone. after: [NE, NE, E*, E, _, _, _, _] ^head ^tail notEmptyCount=3Case 2 — eviction (uncommon, burst wind-down):
before (ring wraps, IDLE* = idle past threshold): [E, NE, _, IDLE*, NE, E, E, NE] ^tail ^head pass 1: IDLE* evicted (markToDeallocate), survivors compacted, stale slots nulled. [_, _, _, NE, E, E, NE, E] ^tail ^head |--- kept=6 ---| pass 2 (partition): [epoch=0 hasCap | 0<epoch<T hasCap | epoch>=T hasCap | noCap]. [_, _, _, NE, NE, E, E, E] ^tail ^head notEmptyCount=2, count=6Idle chunks (remainingCapacity == capacity) age via purgeEpoch and are evicted past threshold, but at leastpurgeRetentionFloorchunks are always retained.
-
-
Field Summary
Fields Modifier and Type Field Description (package private) AdaptivePoolingAllocator.SizeClassedChunk[]chunks(package private) intcount(package private) inthead(package private) intmaxCachedChunks(package private) intnotEmptyCountprivate longpurgeBudget(package private) intpurgeRetentionFloor(package private) inttail
-
Constructor Summary
Constructors Constructor Description ThreadLocalSizeClassedChunkCache(int chunkSize)
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description (package private) AdaptivePoolingAllocator.SizeClassedChunkforcePurge()voidfree()booleanisEmpty()booleanofferChunk(AdaptivePoolingAllocator.Chunk chunk)private voidpartition(int size)AdaptivePoolingAllocator.SizeClassedChunkpollChunk(int size)private voidrunPurgeScan()private AdaptivePoolingAllocator.SizeClassedChunkscanForCapacity()private AdaptivePoolingAllocator.SizeClassedChunkscanForCapacityFallback()java.lang.StringtoString()-
Methods inherited from class io.netty.buffer.AdaptivePoolingAllocator.SizeClassedChunkCache
create
-
-
-
-
Field Detail
-
chunks
AdaptivePoolingAllocator.SizeClassedChunk[] chunks
-
head
int head
-
tail
int tail
-
count
int count
-
notEmptyCount
int notEmptyCount
-
purgeBudget
private long purgeBudget
-
maxCachedChunks
final int maxCachedChunks
-
purgeRetentionFloor
final int purgeRetentionFloor
-
-
Method Detail
-
forcePurge
AdaptivePoolingAllocator.SizeClassedChunk forcePurge()
- Specified by:
forcePurgein classAdaptivePoolingAllocator.SizeClassedChunkCache
-
pollChunk
public AdaptivePoolingAllocator.SizeClassedChunk pollChunk(int size)
- Specified by:
pollChunkin interfaceAdaptivePoolingAllocator.ChunkCache- Specified by:
pollChunkin classAdaptivePoolingAllocator.SizeClassedChunkCache
-
scanForCapacity
private AdaptivePoolingAllocator.SizeClassedChunk scanForCapacity()
-
scanForCapacityFallback
private AdaptivePoolingAllocator.SizeClassedChunk scanForCapacityFallback()
-
runPurgeScan
private void runPurgeScan()
-
partition
private void partition(int size)
-
offerChunk
public boolean offerChunk(AdaptivePoolingAllocator.Chunk chunk)
-
toString
public java.lang.String toString()
- Overrides:
toStringin classjava.lang.Object
-
free
public void free()
-
isEmpty
public boolean isEmpty()
-
-