对象池的作用
- 性能提升:通过重用对象,减少了对象创建和销毁的开销。
- GC友好:减少了GC的压力,因为减少了对象的建和销毁。
Recycler
的内部结构
-
Stack:作为对象池的顶层数据结构,用于存储当前线程回收的对象。在多线程环境中,每个线程通过
FastThreadLocal
持有各自的对象池,避免了锁竞争。 -
WeakOrderQueue:用于存储其他线程回收到当前线程所分配的对象,并在合适的时机由
Stack
收割。 -
Link:在每个
WeakOrderQueue
中包含的链表,用于存储回收的对象。每个Link
节点默认存储一定数量的对象。 -
DefaultHandle:保存实际回收的对象实例,
Stack
和WeakOrderQueue
都使用DefaultHandle
来存储这些对象。
Recycler
的设计理念
- 线程私有化:通过
FastThreadLocal
实现线程私有的对象池,减少多线程间的同步开销。 - 对象回收比率控制:通过
ratioMask
控制对象的回收比率,实现灵活的对象管理策略。 - 弱引用队列:使用
WeakOrderQueue
管理跨线程的对象回收,允许在适当的时候回收其他线程的对象。 - 动态数组:
Stack
使用动态数组elements
存储DefaultHandle
实例,以适应不同数量的对象存储需求。
从Recycler中获取对象
- 获取线程栈缓存:通过
FastThreadLocal
获取当前线程的唯一栈缓存Stack
。 - 尝试弹出对象:尝试从
Stack
中弹出DefaultHandle
对象。 - 创建新对象:如果
Stack
为空,则调用newObject
创建新对象,并将其与DefaultHandle
绑定。
Stack的工作原理
- 弹出对象:如果
Stack
的elements
数组中有对象,则直接弹出。 - 回收对象:如果
elements
数组为空,则调用scavenge
方法尝试从其他线程回收的对象中转移一些到elements
数组中。
scavenge方法
- 从WeakOrderQueue迁移对象:尝试从
WeakOrderQueue
链表中迁移对象实例到Stack
的elements
数组中。 - 处理退出线程的对象:如果线程已退出,其对象实例会被回收,并从
WeakOrderQueue
链表中移除。
对象回收
对象回收的控制
- 回收频率控制:通过
dropHandle
方法控制回收频率,每8个对象中选择一个进行回收。 - Stack扩容:如果回收的对象加上
Stack
中已有的对象数量超过当前容量但小于最大容量,会进行扩容。
对象回收原理
- 同线程回收:直接向
Stack
的elements
数组中添加数据,如果超过最大容量则丢弃对象。 - 异线程回收:与
WeakOrderQueue
直接交互,通过DELAYED_RECYCLED
缓存帮助其他线程回收对象。
异线程对象回收
- 获取WeakOrderQueue:通过
DELAYED_RECYCLED
获取或创建WeakOrderQueue
。 - 添加对象到WeakOrderQueue:将对象添加到
WeakOrderQueue
的Link
链表中,如果超过阈值则丢弃对象。
Netty中的Recycler应用实例
- PooledHeapByteBuf 和 PooledDirectByteBuf:这两种缓冲区分别对应堆内存和直接内存的池化实现。通过对象池,Netty能够重用预先分配的对象实例,减少频繁创建和销毁对象的开销。
- MemoryRegionCache:内存池中,MemoryRegionCache 维护一个队列,队列中的每个Entry节点负责保存内存块。这些Entry节点也是通过对象池进行分配和释放的。
总结
Recycler核心组件
- Stack:作为线程私有的缓存,用于存储可重用的对象。
- WeakOrderQueue:负责跨线程的对象回收,通过链表结构管理各个线程回收的对象。
Recycler对象获取流程
- 优先从Stack获取:当需要一个对象时,Recycler会首先检查当前线程的Stack中是否有可用对象。
- 从WeakOrderQueue迁移:如果Stack为空,Recycler会尝试从WeakOrderQueue中迁移对象到Stack,然后再从Stack中获取。
Recycler对象回收策略
- 同线程回收:当对象不再需要时,如果是在创建它的同一个线程中,Recycler会直接将对象放回Stack中,以便后续重用。
- 异线程回收:如果对象是在不同线程中被回收,Recycler会将对象放入WeakOrderQueue的Link中,等待其他线程帮助回收。
Recycler控制回收频率
- 回收速率控制:为了防止过度回收导致的性能问题,Recycler通过一个算法控制回收频率,确保每8个对象中只有一个被回收,其余的则被丢弃。