谈谈netty内存管理

本文深入探讨了Netty的内存管理机制,包括ByteBuf、PoolChunk、Page、PoolChunkList、PoolSubpage和PoolArena等关键组件。Netty通过一次性向操作系统申请大块内存,然后进行精细管理,提高内存分配和回收效率,降低系统调用开销。PoolChunk以Page为最小管理单元,采用类似Jemalloc的内存组织方式,PoolThreadCache则通过线程本地缓存减少内存分配时的竞争。整个内存管理机制旨在平衡分配速度和内存使用效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

正是Netty的易用性和高性能成就了Netty,让其能够如此流行。
而作为一款通信框架,首当其冲的便是对IO性能的高要求。
不少读者都知道Netty底层通过使用Direct Memory,减少了内核态与用户态之间的内存拷贝,加快了IO速率。但是频繁的向系统申请Direct Memory,并再使用完成后释放本身就是一件影响性能的事情。为此,Netty内部实现了一套自己的内存管理机制,在申请时,Netty会一次性向操作系统申请较大的一块内存,然后再将大内存进行管理,按需拆分成小块分配。而释放时,Netty并不着急直接释放内存,而是将内存回收以待下次使用。
这套内存管理机制不仅可以管理Directory Memory,同样可以管理Heap Memory。

内存的终端消费者——ByteBuf

这里,我想向读者们强调一点,ByteBuf和内存其实是两个概念,要区分理解。
ByteBuf是一个对象,需要给他分配一块内存,它才能正常工作。
而内存可以通俗的理解成我们操作系统的内存,虽然申请到的内存也是需要依赖载体存储的:堆内存时,通过byte[], 而Direct内存,则是Nio的ByteBuffer(因此Java使用Direct Memory的能力是JDK中Nio包提供的)。
为什么要强调这两个概念,是因为Netty的内存池(或者称内存管理机制)涉及的是针对内存的分配和回收,而Netty的ByteBuf的回收则是另一种叫做对象池的技术(通过Recycler实现)。
虽然这两者总是伴随着一起使用,但这二者是独立的两套机制。可能存在着某次创建ByteBuf时,ByteBuf是回收使用的,而内存却是新向操作系统申请的。也可能存在某次创建ByteBuf时,ByteBuf是新创建的,而内存却是回收使用的。
因为对于一次创建过程而言,可以分成三个步骤:

  1. 获取ByteBuf实例(可能新建,也可能是之间缓存的)
  2. 向Netty内存管理机制申请内存(可能新向操作系统申请,也可能是之前回收的)
  3. 将申请到的内存分配给ByteBuf使用

本文只关注内存的管理机制,因此不会过多的对对象回收机制做解释。

Netty中内存管理的相关类

Netty中与内存管理相关的类有很多。框架内部提供了PoolArena,PoolChunkList,PoolChunk,PoolSubpage等用来管理一块或一组内存。
而对外,提供了ByteBufAllocator供用户进行操作。
接下来,我们会先对这几个类做一定程度的介绍,在通过ByteBufAllocator了解内存分配和回收的流程。
为了篇幅和可读性考虑,本文不会涉及到大量很详细的代码说明,而主要是通过图辅之必要的代码进行介绍。
针对代码的注解,可以见我GitHub上的netty项目。

PoolChunck——Netty向OS申请的最小内存

上文已经介绍了,为了减少频繁的向操作系统申请内存的情况,Netty会一次性申请一块较大的内存。而后对这块内存进行管理,每次按需将其中的一部分分配给内存使用者(每ByteBuf)。这里的内存就是PoolChunk,其大小由ChunkSize决定(默认为16M,即一次向OS申请16M的内存)。

Page——PoolChunck所管理的最小内存单位

PoolChunk所能管理的最小内存叫做Page

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值