• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

netty-池化内存-PoolThreadCache

互联网 diligentman 2周前 (11-19) 11次浏览

PoolThreadCache

池化内存分配缓存,就类放在线程局部变量中,回收内存时,优先扔在这个类的容器中,后面直接拿出来分配

netty-池化内存-PoolThreadCache

属性

看类先看属性,根据属性可以猜出该类的功能

final PoolArena<byte[]> heapArena;
    final PoolArena<ByteBuffer> directArena;

    // Hold the caches for the different size classes, which are tiny, small and normal.
   //下面6个数组分直接内存与堆内存,有三种按大小的内存分配方式,0-512,512-2048, > 2048
    private final MemoryRegionCache<byte[]>[] tinySubPageHeapCaches;
    private final MemoryRegionCache<byte[]>[] smallSubPageHeapCaches;
    private final MemoryRegionCache<ByteBuffer>[] tinySubPageDirectCaches;
    private final MemoryRegionCache<ByteBuffer>[] smallSubPageDirectCaches;
    private final MemoryRegionCache<byte[]>[] normalHeapCaches;
    private final MemoryRegionCache<ByteBuffer>[] normalDirectCaches;

    // Used for bitshifting when calculate the index of normal caches later
    private final int numShiftsNormalDirect;//log2(pageSize)
    private final int numShiftsNormalHeap;
    private final int freeSweepAllocationThreshold;//分配次数达到阀值,将剩下未分配的回收掉
    private final AtomicBoolean freed = new AtomicBoolean();

    private int allocations;//已分配内存次数

重要方法

       //tinyCacheSize=512   numTinySubpagePools=32
            tinySubPageDirectCaches = createSubPageCaches(
                    tinyCacheSize, PoolArena.numTinySubpagePools, SizeClass.Tiny);
    //smallCacheSize=256   numTinySubpagePools=4
            smallSubPageDirectCaches = createSubPageCaches(
                    smallCacheSize, directArena.numSmallSubpagePools, SizeClass.Small);

            numShiftsNormalDirect = log2(directArena.pageSize);

    //normalCacheSize=64   maxCachedBufferCapacity=8192
            normalDirectCaches = createNormalCaches(
                    normalCacheSize, maxCachedBufferCapacity, directArena);

内存分配

 //三种大小的内存分配,如果缓存没有现成的,返回分配失败
    /**
     * Try to allocate a tiny buffer out of the cache. Returns {@code true} if successful {@code false} otherwise
     */
    boolean allocateTiny(PoolArena<?> area, PooledByteBuf<?> buf, int reqCapacity, int normCapacity) {
        return allocate(cacheForTiny(area, normCapacity), buf, reqCapacity);
    }

    /**
     * Try to allocate a small buffer out of the cache. Returns {@code true} if successful {@code false} otherwise
     */
    boolean allocateSmall(PoolArena<?> area, PooledByteBuf<?> buf, int reqCapacity, int normCapacity) {
        return allocate(cacheForSmall(area, normCapacity), buf, reqCapacity);
    }

    /**
     * Try to allocate a small buffer out of the cache. Returns {@code true} if successful {@code false} otherwise
     */
    boolean allocateNormal(PoolArena<?> area, PooledByteBuf<?> buf, int reqCapacity, int normCapacity) {
        return allocate(cacheForNormal(area, normCapacity), buf, reqCapacity);
    }

计算数组下标

分配tiny

    private MemoryRegionCache<?> cacheForTiny(PoolArena<?> area, int normCapacity) {
        int idx = PoolArena.tinyIdx(normCapacity);
        if (area.isDirect()) {
            return cache(tinySubPageDirectCaches, idx);
        }
        return cache(tinySubPageHeapCaches, idx);
    }


    static int tinyIdx(int normCapacity) {
        return normCapacity >>> 4; // 最低15个字节,最大512字节,数组大小也是按512>>>4来计算的,这种方式可以保证数组每个元素放的内存大小是一样的
    }

分配small

    private MemoryRegionCache<?> cacheForSmall(PoolArena<?> area, int normCapacity) {
        int idx = PoolArena.smallIdx(normCapacity);
        if (area.isDirect()) {
            return cache(smallSubPageDirectCaches, idx);
        }
        return cache(smallSubPageHeapCaches, idx);
    }

    static int smallIdx(int normCapacity) {
        int tableIdx = 0;
        int i = normCapacity >>> 10;//为什么右移10位,是因为这里需要大于512并且接近2N次方,最近的值就是1024,/1024就是>>10,  数据的个数也是pageSize/1024 = pageShift-9。为什么减9,而不是10,如果减10,pageSize=1024,那么数组的个数就是0
        while (i != 0) {//这里内存是按2N次方分配,所以要额外处理一下
            i >>>= 1;
            tableIdx ++;
        }
        return tableIdx;
    }

分配normal

    private static <T> MemoryRegionCache<T>[] createNormalCaches(
            int cacheSize, int maxCachedBufferCapacity, PoolArena<T> area) {
        if (cacheSize > 0 && maxCachedBufferCapacity > 0) {
            int max = Math.min(area.chunkSize, maxCachedBufferCapacity);//缓存最大申请内存,超过该值的不缓存
            int arraySize = Math.max(1, log2(max / area.pageSize) + 1);//算出最大内存有多少种分配方式,内存是按照2的N次方来分配的

            @SuppressWarnings("unchecked")
            MemoryRegionCache<T>[] cache = new MemoryRegionCache[arraySize];
            for (int i = 0; i < cache.length; i++) {
                cache[i] = new NormalMemoryRegionCache<T>(cacheSize);
            }
            return cache;
        } else {
            return null;
        }
    }

    private MemoryRegionCache<?> cacheForNormal(PoolArena<?> area, int normCapacity) {
        if (area.isDirect()) {
            int idx = log2(normCapacity >> numShiftsNormalDirect);
            return cache(normalDirectCaches, idx);
        }
       //也可以用  log2(normCapacity/pageSize)
        int idx = log2(normCapacity >> numShiftsNormalHeap);
        return cache(normalHeapCaches, idx);
    }

喜欢 (0)