netty源码之内存池
Posted better_hui
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了netty源码之内存池相关的知识,希望对你有一定的参考价值。
目录
一、DirectBuffer 和 HeapBuffer
对外直接内存缓冲
directBuffer是分配在直接内存(Direct Memory)上的内存区域,直接内存不是JVM 运行时数据区的一部分,也不是JVM规范定义的内存区域。
在jdk1.4开始NIO引入了Channel 和 Buffer的API包,我们可以通过调用native接口来申请直接内存,并关联一个JVM上的引用,当JVM内存上引用收回后 这块直接内存才能被操作系统回收。
堆内存缓冲
heapBuffer是分配在JVM堆内存区域的缓冲区,我们可以人为是一个byte[] 数组的封装形式、
IO
1、基于堆内存的IO操作 , 首先在堆内存申请一块内存数据 , 然后将数据copy至直接内存 , 然后再将直接内存上的数据发送到IO设备的缓冲区。
2、基于直接内存的IO操作 , 避免了堆内存到直接内存的数据copy ,加快访问速度,大大的提高性能。
3、DirectBuffer的缺点在于直接内存的分配与释放的代价相对比较大,因此,其适用于可复用的缓冲区
二、Netty的池化
池化的好处
1、资源的复用 , 减少内存申请和释放的性能损耗
2、减轻GC压力 , 避免内存抖动
3、内存资源可控
netty的缓冲池
在netty中,缓冲区有两种HeapBuffer 和 DirectBuffer ;
对应堆内存和直接内存的池化技术分别是PooledHeapByteBuf 和 PooledDirectByteBuf
使用
1、池化Buffer
netty通过PooledByteBufAllocator 可以创建基于内存池分配的ByteBuf对象(PooledHeapByteBuf、PooledDirectByteBuf),这样就避免了每次消息读写都申请和释放ByteBuf,这样很大程度减少了gc的次数,对性能提升是非常可观的
2、非池化Buffer
netty通过UnpooledByteBufAllocator可以创建非池化的ByteBuf对象
三、内存分配
启动的时候 , 我们可以设置内存分配是采用池化或者非池化的方式 。默认采用池化技术。
1、PooledDirectByteBuf对象池的使用
跟进RECYCLER.get()
源码
@SuppressWarnings("unchecked") public final T get() // 判断线程池的容量等于0则直接返回一个Object if (maxCapacityPerThread == 0) return newObject((Handle<T>) NOOP_HANDLE); // fastThreadLocal中获取一个stack Stack<T> stack = threadLocal.get(); DefaultHandle<T> handle = stack.pop(); // 试图从"池"中取一个handle,如果没有成功就new一个handle if (handle == null) handle = stack.newHandle(); handle.value = newObject(handle); return (T) handle.value;
在类中方法内回收对象的实现
private static final class DefaultHandle<T> implements Handle<T> // 默认的回收对象的实现方式 @Override public void recycle(Object object) stack.push(this);// 将对象再放入栈中
2、回收池Recycler原理
对象池通过Recycler里面WeakOrderQueue、Stack 2个类来实现。 首先放一张图来展示一个stack中两者的关系:
1、为避免并发安全,每个线程都有自己的线程池,stack作为本线程对象池的核心,通过FastThreadLocal实现每个线程的本地化
3、堆外内存的分配
进入PooledByteBufAllocator
的构造函数
继续跟进源码,传入的preferDirect
最后作用于directByDefault
,然后当directByDefault
为true的时候,115行的代码会分配一个堆外内存
最终是调用了jdk的对外内存分配方法
四、apache的对象池
commons-pool
Apache Commons Pool开源软件库提供了一个对象池API和一系列对象池的实现,支持各种配置,比如活跃对象数或者闲置对象个数等。DBCP数据库连接池基于Apache Commons Pool实现。
以上是关于netty源码之内存池的主要内容,如果未能解决你的问题,请参考以下文章