1. 程式人生 > >Netty原始碼之directArena分配direct記憶體的流程

Netty原始碼之directArena分配direct記憶體的流程

這個流程分為以下幾個步驟: 1、從物件池裡面拿到PooledByteBuf進行復用 2、從快取上進行記憶體分配 3、從記憶體堆裡面進行分配 接下來我們跟到程式碼裡面去看一下,回到newDirectBuffer這個方法:

protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) {
        //拿到當前執行緒中的記憶體池
        PoolThreadCache cache = threadCache.get();
        //拿到當前記憶體池裡面的directArena進行分配
        PoolArena<ByteBuffer> directArena = cache.directArena;

        ByteBuf buf;
        if (directArena != null) {
            buf = directArena.allocate(cache, initialCapacity, maxCapacity);
        } else {
            if (PlatformDependent.hasUnsafe()) {
                buf = UnsafeByteBufUtil.newUnsafeDirectByteBuf(this, initialCapacity, maxCapacity);
            } else {
                buf = new UnpooledDirectByteBuf(this, initialCapacity, maxCapacity);
            }
        }

        return toLeakAwareBuffer(buf);
    }

這個方法做了兩件事: 1、拿到當前執行緒的記憶體池 2、拿到記憶體池裡面的directArena進行記憶體分配 這個方法上一篇講過了,我們直接進入記憶體分配的方法裡面去看一下:

 PooledByteBuf<T> allocate(PoolThreadCache cache, int reqCapacity, int maxCapacity) {
 		//拿到一個物件
        PooledByteBuf<T> buf = newByteBuf(maxCapacity);
        //給這個物件分配記憶體空間
        allocate(cache, buf, reqCapacity);
        return buf;
    }

這個方法很清晰,就是先通過newByteBuf方法拿一個PooledByteBuf物件,然後通過allocate給這個物件分配記憶體:

protected PooledByteBuf<ByteBuffer> newByteBuf(int maxCapacity) {
            if (HAS_UNSAFE) {
                return PooledUnsafeDirectByteBuf.newInstance(maxCapacity);
            } else {
                return PooledDirectByteBuf.newInstance(maxCapacity);
            }
        }

由於預設情況下是unsafe的,所以我們進入第一個分支去看一下:

static PooledUnsafeDirectByteBuf newInstance(int maxCapacity) {
		//拿到一個buf
        PooledUnsafeDirectByteBuf buf = RECYCLER.get();
        //重新利用這個buf
        buf.reuse(maxCapacity);
        return buf;
    }

首先會從回收的物件池裡面拿一個物件進行復用,如果沒有拿到就重新建立一個。

final void reuse(int maxCapacity) {
        maxCapacity(maxCapacity);
        setRefCnt(1);
        setIndex0(0, 0);
        discardMarks();
    }

設定一些初始引數。 到這裡我們就拿到了一個buf物件,接下來就要對他進行記憶體分配。首先通過快取進行記憶體分配,如果失敗就會通過Aren/進行分配。

if (normCapacity <= chunkSize) {
            if (cache.allocateNormal(this, buf, reqCapacity, normCapacity)) {
                // was able to allocate out of the cache so move on
                return;
            }
            allocateNormal(buf, reqCapacity, normCapacity);
        } 

以這段程式碼為例。 這節我們主要是簡單介紹一下大體上記憶體分配的流程,那麼,之後我們就會對各種記憶體規格的分配進行詳細的講解。