final class PoolThreadCache {
final PoolArena<byte[]> heapArena;
final PoolArena<ByteBuffer> directArena;
//分別存儲堆外和堆內的內存,MemoryRegionCache內部結構是鏈表
private final MemoryRegionCache<byte[]>[] tinySubPageHeapCaches; //默認長度32
private final MemoryRegionCache<byte[]>[] smallSubPageHeapCaches; //默認長度4
private final MemoryRegionCache<ByteBuffer>[] tinySubPageDirectCaches; //默認長度32
private final MemoryRegionCache<ByteBuffer>[] smallSubPageDirectCaches;//默認長度4
private final MemoryRegionCache<byte[]>[] normalHeapCaches; //默認長度3
private final MemoryRegionCache<ByteBuffer>[] normalDirectCaches; //默認長度3
// Used for bitshifting when calculate the index of normal caches later
//移位使用的偏移量,在計算normalCaches數組下標時使用
private final int numShiftsNormalDirect; //13
private final int numShiftsNormalHeap; //13
private final int freeSweepAllocationThreshold; //8192
private final AtomicBoolean freed = new AtomicBoolean();
private int allocations;
PoolThreadCache(PoolArena<byte[]> heapArena, PoolArena<ByteBuffer> directArena,
int tinyCacheSize, int smallCacheSize, int normalCacheSize,
int maxCachedBufferCapacity, int freeSweepAllocationThreshold) {
if (maxCachedBufferCapacity < 0) {
throw new IllegalArgumentException("maxCachedBufferCapacity: "
+ maxCachedBufferCapacity + " (expected: >= 0)");
}
this.freeSweepAllocationThreshold = freeSweepAllocationThreshold;
this.heapArena = heapArena;
this.directArena = directArena;
if (directArena != null) {
tinySubPageDirectCaches = createSubPageCaches(
tinyCacheSize, PoolArena.numTinySubpagePools, SizeClass.Tiny);
smallSubPageDirectCaches = createSubPageCaches(
smallCacheSize, directArena.numSmallSubpagePools, SizeClass.Small);
numShiftsNormalDirect = log2(directArena.pageSize);
normalDirectCaches = createNormalCaches(
normalCacheSize, maxCachedBufferCapacity, directArena);
directArena.numThreadCaches.getAndIncrement();
} else {
// No directArea is configured so just null out all caches
tinySubPageDirectCaches = null;
smallSubPageDirectCaches = null;
normalDirectCaches = null;
numShiftsNormalDirect = -1;
}
if (heapArena != null) {
// Create the caches for the heap allocations
tinySubPageHeapCaches = createSubPageCaches(
tinyCacheSize, PoolArena.numTinySubpagePools, SizeClass.Tiny);
smallSubPageHeapCaches = createSubPageCaches(
smallCacheSize, heapArena.numSmallSubpagePools, SizeClass.Small);
numShiftsNormalHeap = log2(heapArena.pageSize);
normalHeapCaches = createNormalCaches(
normalCacheSize, maxCachedBufferCapacity, heapArena);
heapArena.numThreadCaches.getAndIncrement();
} else {
// No heapArea is configured so just null out all caches
tinySubPageHeapCaches = null;
smallSubPageHeapCaches = null;
normalHeapCaches = null;
numShiftsNormalHeap = -1;
}
// Only check if there are caches in use.
if ((tinySubPageDirectCaches != null || smallSubPageDirectCaches != null || normalDirectCaches != null
|| tinySubPageHeapCaches != null || smallSubPageHeapCaches != null || normalHeapCaches != null)
&& freeSweepAllocationThreshold < 1) {
throw new IllegalArgumentException("freeSweepAllocationThreshold: "
+ freeSweepAllocationThreshold + " (expected: > 0)");
}
}
//創建緩存數組,numCaches爲數組長度,cacheSize爲隊列長度
private static <T> MemoryRegionCache<T>[] createSubPageCaches(
int cacheSize, int numCaches, SizeClass sizeClass) {
if (cacheSize > 0 && numCaches > 0) {
//初始化數組
MemoryRegionCache<T>[] cache = new MemoryRegionCache[numCaches];
for (int i = 0; i < cache.length; i++) {
//數組元素賦值,SubPageMemoryRegionCache內部包含一個隊列,存儲PoolChunk
//cacheSize=隊列容量,sizeClass=爲Tiny或Small
cache[i] = new SubPageMemoryRegionCache<T>(cacheSize, sizeClass);
}
return cache;
} else {
return null;
}
}
//cacheSize默認64 maxCachedBufferCapacity默認32768(8192*4)
private static <T> MemoryRegionCache<T>[] createNormalCaches(
int cacheSize, int maxCachedBufferCapacity, PoolArena<T> area) {
if (cacheSize > 0 && maxCachedBufferCapacity > 0) {
//max=32768
int max = Math.min(area.chunkSize, maxCachedBufferCapacity);
//arraySize=3, log2(N),其實就是 N除以2的結果
int arraySize = Math.max(1, log2(max / area.pageSize) + 1);
MemoryRegionCache<T>[] cache = new MemoryRegionCache[arraySize];
for (int i = 0; i < cache.length; i++) {
//cacheSize=64默認,爲隊列的容量
cache[i] = new NormalMemoryRegionCache<T>(cacheSize);
}
return cache;
} else {
return null;
}
}
//val除以2的結果
private static int log2(int val) {
int res = 0;
while (val > 1) {
val >>= 1;
res++;
}
return res;
}
boolean allocateTiny(PoolArena<?> area, PooledByteBuf<?> buf, int reqCapacity, int normCapacity) {
return allocate(cacheForTiny(area, normCapacity), buf, reqCapacity);
}
boolean allocateSmall(PoolArena<?> area, PooledByteBuf<?> buf, int reqCapacity, int normCapacity) {
return allocate(cacheForSmall(area, normCapacity), buf, reqCapacity);
}
boolean allocateNormal(PoolArena<?> area, PooledByteBuf<?> buf, int reqCapacity, int normCapacity) {
return allocate(cacheForNormal(area, normCapacity), buf, reqCapacity);
}
//分配緩存
private boolean allocate(MemoryRegionCache<?> cache, PooledByteBuf buf, int reqCapacity) {
if (cache == null) {
// no cache found so just return false here
return false;
}
//分配緩存
boolean allocated = cache.allocate(buf, reqCapacity);
//分配次數>=8192
if (++ allocations >= freeSweepAllocationThreshold) {
allocations = 0;
//釋放掉緩存
trim();
}
return allocated;
}
//把PoolChunk根據大小不同,選擇對應的MemoryRegionCache,然後加入到隊列
boolean add(PoolArena<?> area, PoolChunk chunk, long handle, int normCapacity, SizeClass sizeClass) {
MemoryRegionCache<?> cache = cache(area, normCapacity, sizeClass);
if (cache == null) {
return false;
}
return cache.add(chunk, handle);
}
//根據請求大小,選擇對應的緩存對象
private MemoryRegionCache<?> cache(PoolArena<?> area, int normCapacity, SizeClass sizeClass) {
switch (sizeClass) {
case Normal:
return cacheForNormal(area, normCapacity);
case Small:
return cacheForSmall(area, normCapacity);
case Tiny:
return cacheForTiny(area, normCapacity);
default:
throw new Error();
}
}
//當前Cache被垃圾回收時會被調用
@Override
protected void finalize() throws Throwable {
try {
super.finalize();
} finally {
free();
}
}
//釋放所有資源
void free() {
//釋放所有資源,線程安全判斷,只釋放一次
if (freed.compareAndSet(false, true)) {
int numFreed = free(tinySubPageDirectCaches) +
free(smallSubPageDirectCaches) +
free(normalDirectCaches) +
free(tinySubPageHeapCaches) +
free(smallSubPageHeapCaches) +
free(normalHeapCaches);
//directArena線程引用計數器減一
if (directArena != null) {
directArena.numThreadCaches.getAndDecrement();
}
//heapArena線程引用計數器減一
if (heapArena != null) {
heapArena.numThreadCaches.getAndDecrement();
}
}
}
//釋放緩存數組
private static int free(MemoryRegionCache<?>[] caches) {
if (caches == null) {
return 0;
}
int numFreed = 0;
for (MemoryRegionCache<?> c: caches) {
numFreed += free(c);
}
return numFreed;
}
//把緩存內部隊列中所有chunk釋放掉
private static int free(MemoryRegionCache<?> cache) {
if (cache == null) {
return 0;
}
return cache.free();
}
//把所有類型的緩存數組全部釋放一遍,具體釋放邏輯看其實現
void trim() {
trim(tinySubPageDirectCaches);
trim(smallSubPageDirectCaches);
trim(normalDirectCaches);
trim(tinySubPageHeapCaches);
trim(smallSubPageHeapCaches);
trim(normalHeapCaches);
}
//釋放caches數組
private static void trim(MemoryRegionCache<?>[] caches) {
if (caches == null) {
return;
}
//循環每個cache元素釋放
for (MemoryRegionCache<?> c: caches) {
trim(c);
}
}
private static void trim(MemoryRegionCache<?> cache) {
if (cache == null) {
return;
}
cache.trim();
}
private MemoryRegionCache<?> cacheForTiny(PoolArena<?> area, int normCapacity) {
//normCapacity >>> 4; 根據normCapacity計算出tiny緩存數組下標
//數組長度32,每個元素對應不用的大小,從16個字節大小開始,每次增加16個字節。
int idx = PoolArena.tinyIdx(normCapacity);
if (area.isDirect()) {
return cache(tinySubPageDirectCaches, idx);
}
return cache(tinySubPageHeapCaches, idx);
}
private MemoryRegionCache<?> cacheForSmall(PoolArena<?> area, int normCapacity) {
//根據normCapacity計算small緩存數組下標,數組長度爲4,[512,1024,2048,4096]
int idx = PoolArena.smallIdx(normCapacity);
if (area.isDirect()) {
return cache(smallSubPageDirectCaches, idx);
}
return cache(smallSubPageHeapCaches, idx);
}
private MemoryRegionCache<?> cacheForNormal(PoolArena<?> area, int normCapacity) {
if (area.isDirect()) {
//numShiftsNormalDirect默認爲13,相當於除以8192
//這裏如果idx不大於3的話,那麼normCapacity最大爲5*8192
int idx = log2(normCapacity >> numShiftsNormalDirect);
return cache(normalDirectCaches, idx);
}
int idx = log2(normCapacity >> numShiftsNormalHeap);
return cache(normalHeapCaches, idx);
}
private static <T> MemoryRegionCache<T> cache(MemoryRegionCache<T>[] cache, int idx) {
//如果下標越界返回null
if (cache == null || idx > cache.length - 1) {
return null;
}
return cache[idx];
}
//TINY or SMALL 大小的緩存,使用Subpage來分配
private static final class SubPageMemoryRegionCache<T> extends MemoryRegionCache<T> {
SubPageMemoryRegionCache(int size, SizeClass sizeClass) {
super(size, sizeClass);
}
@Override
protected void initBuf(
PoolChunk<T> chunk, long handle, PooledByteBuf<T> buf, int reqCapacity) {
chunk.initBufWithSubpage(buf, handle, reqCapacity);
}
}
//Normal大小的緩存,使用chunk.initBuf按整塊分配
private static final class NormalMemoryRegionCache<T> extends MemoryRegionCache<T> {
NormalMemoryRegionCache(int size) {
super(size, SizeClass.Normal);
}
//按整塊分配
@Override
protected void initBuf(
PoolChunk<T> chunk, long handle, PooledByteBuf<T> buf, int reqCapacity) {
chunk.initBuf(buf, handle, reqCapacity);
}
}
//緩存元素,內部一個隊列存儲每個PoolChunk
private abstract static class MemoryRegionCache<T> {
private final int size;
private final Queue<Entry<T>> queue;
private final SizeClass sizeClass;
private int allocations;
MemoryRegionCache(int size, SizeClass sizeClass) {
//以2的次方進行增長,比如傳入3返回4,傳入5返回8,傳入9返回16。
this.size = MathUtil.safeFindNextPositivePowerOfTwo(size);
//定長隊列
queue = PlatformDependent.newFixedMpscQueue(this.size);
//緩存類型 tiny small normal
this.sizeClass = sizeClass;
}
//初始化PooledByteBuf,子類實現,根據tiny,small或Normal有不同的處理方式
protected abstract void initBuf(PoolChunk<T> chunk, long handle,
PooledByteBuf<T> buf, int reqCapacity);
//把chunk加入隊列,如果隊列滿了返回false
public final boolean add(PoolChunk<T> chunk, long handle) {
//創建Entry
Entry<T> entry = newEntry(chunk, handle);
//隊列滿了返回false
boolean queued = queue.offer(entry);
if (!queued) {
//加入失敗回收entry
entry.recycle();
}
return queued;
}
//分配內存
public final boolean allocate(PooledByteBuf<T> buf, int reqCapacity) {
//獲取並移除元素,元素不存在返回false
Entry<T> entry = queue.poll();
if (entry == null) {
return false;
}
//元素存在則一定分配成功
initBuf(entry.chunk, entry.handle, buf, reqCapacity);
//回收entry
entry.recycle();
//分配數量增加
++ allocations;
return true;
}
//把隊列中所有元素釋放
public final int free() {
return free(Integer.MAX_VALUE);
}
//釋放固定次數
private int free(int max) {
int numFreed = 0;
//釋放固定次數,假設隊列30個元素,如果max=10,那就把隊列中前10個元素釋放掉
for (; numFreed < max; numFreed++) {
Entry<T> entry = queue.poll();
if (entry != null) {
freeEntry(entry);
} else {
return numFreed;
}
}
return numFreed;
}
//這個方法是用於優化目的,把不常用的緩存釋放掉
//allocations這個值是一段時間當前緩存被使用的次數
public final void trim() {
int free = size - allocations;
allocations = 0;
if (free > 0) {
free(free);
}
}
//真正釋放緩存
private void freeEntry(Entry entry) {
PoolChunk chunk = entry.chunk;
long handle = entry.handle;
//entry對象是池化的,回收它。
entry.recycle();
//真正釋放,堆內被GC,堆外使用UNSAFE釋放內存空間
chunk.arena.freeChunk(chunk, handle, sizeClass);
}
//Entry 一個池化對象,可以重複利用,內部存儲PoolChunk和handle
static final class Entry<T> {
final Handle<Entry<?>> recyclerHandle;
PoolChunk<T> chunk;
long handle = -1;
Entry(Handle<Entry<?>> recyclerHandle) {
this.recyclerHandle = recyclerHandle;
}
void recycle() {
chunk = null;
handle = -1;
recyclerHandle.recycle(this);
}
}
//從池中獲取Entry
private static Entry newEntry(PoolChunk<?> chunk, long handle) {
Entry entry = RECYCLER.get();
entry.chunk = chunk;
entry.handle = handle;
return entry;
}
private static final Recycler<Entry> RECYCLER = new Recycler<Entry>() {
@SuppressWarnings("unchecked")
@Override
protected Entry newObject(Handle<Entry> handle) {
return new Entry(handle);
}
};
}
}