Netty技术全解析:PooledByteBufAllocator源码视角下的详解

news2024/12/26 21:02:04
❃博主首页 : 「码到三十五」 ,同名公众号 :「码到三十五」,wx号 : 「liwu0213」
☠博主专栏 : <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关>
♝博主的话 : 搬的每块砖,皆为峰峦之基;公众号搜索「码到三十五」关注这个爱发技术干货的coder,一起筑基

Netty,作为一款高性能的网络编程框架,其背后的内存管理机制起着至关重要的作用。其中,PooledByteBufAllocator是Netty内存管理中的一个核心组件,它实现了基于内存池的字节缓冲区(ByteBuf)分配策略。本文将结合源码,深入探讨PooledByteBufAllocator的工作原理、实现细节以及其在Netty中的作用。

一、PooledByteBufAllocator概述

PooledByteBufAllocator是Netty提供的一种ByteBufAllocator实现,它使用内存池来管理ByteBuf的分配和回收。相比不使用内存池的分配器(如UnpooledByteBufAllocator),PooledByteBufAllocator能够显著减少内存的分配和回收开销,提高性能。

二、工作原理

PooledByteBufAllocator的工作原理是围绕内存池化技术展开的,它通过预先分配和重用内存块来减少内存分配和释放的开销,从而提高性能.

1. 内存池初始化
  • PoolArena数组PooledByteBufAllocator内部维护了一个PoolArena数组,每个PoolArena代表一块连续的内存区域。这些PoolArena可以被多个线程共享,但在高并发场景下,Netty会创建与线程数量相等的PoolArena实例,以减少线程间的竞争。
  • Chunk和Page:每个PoolArena由多个PoolChunkList组成,每个PoolChunkList包含多个PoolChunkPoolChunk是内存分配的基本单位,默认大小为16MB(这个值可以根据需要调整)。每个PoolChunk又被划分为多个Page,每个Page的大小通常为8KB(这个值也是可配置的)。
2. 内存分配

当需要分配一个新的ByteBuf时,PooledByteBufAllocator会遵循以下步骤:

  • 线程局部缓存(PoolThreadCache):首先,Netty会尝试从当前线程的PoolThreadCache中分配内存。PoolThreadCache是保存在ThreadLocal上的,因此每个线程都有自己独立的缓存,这有助于减少线程间的竞争。

  • PoolArena分配:如果PoolThreadCache中没有足够的内存可供分配,Netty会转向对应的PoolArena进行内存分配。在PoolArena中,Netty会根据请求的内存大小选择不同的分配策略。

    • Tiny和Small内存分配:对于小于Page大小(通常为8KB)的内存请求,Netty会使用tinySubpagePoolssmallSubpagePools进行分配。这些子页池会将Page进一步划分为更小的内存块,以满足小内存请求的需求。
    • Normal内存分配:对于大于等于Page大小但小于Chunk大小的内存请求,Netty会直接在Page上进行分配。
    • Huge内存分配:对于大于Chunk大小的内存请求,Netty会分配一个独立的Chunk给请求者,但这通常不是池化内存的一部分。
  • 内存规格化:在分配内存时,Netty会对请求的内存大小进行规格化,以确保分配的内存块大小是标准的、易于管理的。例如,如果请求的内存大小为20字节,Netty可能会将其规格化为32字节。

3. 内存回收

ByteBuf不再需要时,Netty会将其释放回内存池。释放过程遵循以下步骤:

  • PoolThreadCache回收:首先,Netty会尝试将释放的ByteBuf缓存到当前线程的PoolThreadCache中,以便后续重用。
  • PoolArena回收:如果PoolThreadCache已满或无法缓存释放的ByteBuf,Netty会将其释放回对应的PoolArena。在PoolArena中,释放的内存块会被标记为空闲,并添加到空闲列表中。
4. 内存清理

为了防止内存泄漏,Netty会定期清理内存池中的无效内存块。这通常包括检查空闲列表中的内存块,移除长时间未被使用的内存块,以及回收那些不再需要的Chunk。

5. 并发优化

在高并发场景下,Netty通过以下方式优化PooledByteBufAllocator的性能:

  • 多个PoolArena实例:为每个线程或每个CPU核心分配一个独立的PoolArena实例,以减少线程间的竞争。
  • 线程绑定:Netty在分配内存时会尽量将内存块分配给请求它的线程绑定的PoolArena,以减少跨线程操作。
  • 缓存策略:通过PoolThreadCache为每个线程提供独立的缓存,减少线程间的内存分配竞争。

综上所述,PooledByteBufAllocator通过内存池化技术、线程局部缓存、规格化内存分配和回收策略以及并发优化等措施,实现了高效的内存管理,为Netty的高性能网络通信提供了有力支持。

三、源码解析

以下是PooledByteBufAllocator的一些关键源码:

public class PooledByteBufAllocator extends ByteBufAllocator {
    // 内存池数组,用于存储不同大小的内存池
    private final PoolChunkList<PooledByteBuf<byte[]>>[] chunkLists;
    // ... 其他字段 ...

    @Override
    protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) {
        PoolThreadCache cache = threadCache.get();
        PoolArena<byte[]> directArena = cache.directArena();

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

        return toLeakAwareBuffer(buf);
    }

    // ... 其他方法 ...
}

在上面的代码中,newDirectBuffer方法是PooledByteBufAllocator用于分配新的直接内存ByteBuf的实现。它首先尝试从线程缓存(PoolThreadCache)中获取一个内存池(PoolArena),然后从该内存池中分配一个新的ByteBuf。如果线程缓存中没有可用的内存池,它将使用UnsafeByteBufUtilUnpooledDirectByteBuf来分配一个新的ByteBuf

四、内存池管理

PooledByteBufAllocator使用一组内存池来管理ByteBuf的分配和回收。每个内存池由多个内存块组成,每个内存块可以存储多个ByteBuf实例。内存池的管理包括内存块的分配、回收和清理等操作。

当需要分配一个新的ByteBuf时,PooledByteBufAllocator会首先查找一个合适的空闲内存块,并在其中分配一个新的ByteBuf。如果内存块中没有足够的空间,它会创建一个新的内存块,并将其添加到内存池中。

ByteBuf被释放时,PooledByteBufAllocator会将其标记为空闲,并将其添加到内存块的空闲列表中。如果内存块中的所有ByteBuf都被释放了,该内存块将被添加到内存池的空闲列表中,以便后续重用。

五、性能优势

使用PooledByteBufAllocator相比不使用内存池的分配器具有显著的性能优势。通过内存池化,它可以减少内存的分配和回收开销,降低垃圾回收(GC)的影响,并提高内存的利用率。这使得PooledByteBufAllocator成为Netty中处理大量网络数据时的高效选择。

六、总结

PooledByteBufAllocator是Netty中基于内存池的ByteBuf分配器实现。它通过内存池来管理ByteBuf的分配和回收,显著减少了内存的分配和回收开销,提高了性能。本文结合源码详细介绍了PooledByteBufAllocator的工作原理、实现细节以及其在Netty中的作用,希望对读者深入理解Netty的内存管理机制有所帮助。


关注公众号[码到三十五]获取更多技术干货 !

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1960545.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL---JDBC

一、JDBC是什么&#xff1f; JDBC(Java Database Connectivity):是Java访问数据库的解决方案。 JDBC定义了一套标准的接口&#xff0c;即访问数据库的通用API&#xff0c;不同数据库的厂商根据各自数据库的特点实现这些接口。 JDBC希望用相同的方式访问不同的数据库&#xff0c…

spring:xml定义bean

spring有两种方法定义bean&#xff0c;一种是使用xml标签&#xff0c;一种是注解。在这里介绍使用xml标签定义bean。 我的文件目录如上图所示&#xff0c;在这里创建了bean.xml文件&#xff0c;bean.xml文件中定义了bean。 文件内容&#xff1a; <?xml version"1.0&…

Java线程池动态内存队列思路

背景 在我们定义线程池时候&#xff0c;需要创建一个对列用来存储未执行而排队的任务&#xff0c;这个队列长度问题一直都是需要开发人员斟酌考虑点。在阿里巴巴开发手册中有怎么一个规则如&#xff1a; 说明: Executors返回的线程池对象的弊端如下 FixedThreadPool和SingleT…

【前端面试】七、算法-递归

遍历方法总结 链式调用 数组的很多操作可以构成链式操作&#xff0c;类似这样的格式&#xff1a;…map().filter(…).sort(…).map(….)链式操作就是对象方法返回类型是自身的。比如map是属于数组的方法&#xff0c;它返回数组&#xff0c;所以构成了链式操作优势&#xff1a;…

【iOS】——持久化

在iOS开发中&#xff0c;数据持久化是非常重要的&#xff0c;因为它允许应用程序在不同会话之间保存用户数据、设置、偏好等信息。 为什么数据持久化 数据保存&#xff1a; 目的&#xff1a;将应用程序中的数据保存到非易失性存储中&#xff0c;以便在应用程序关闭或重启后仍…

眼镜清洗机哪个品牌好?性价比高的超声波眼镜清洗机

清洁眼镜、化妆刷、项链等物品其实是挺麻烦的&#xff0c;尤其是化妆刷这种经常使用的物品&#xff0c;需要用专门的清洁剂并保持一定的清洗频率。眼镜的日常清洁主要是用眼镜布擦拭镜片上的灰尘和指纹&#xff0c;但对于顽固的污渍或油脂&#xff0c;只有超声波清洗机能提供快…

六西格玛管理法

六西格玛管理法是一种旨在提高业务流程效率和减少缺陷的管理策略。它最初由摩托罗拉公司在1980年代末期提出&#xff0c;并随后被通用电气等公司广泛应用和发展。六西格玛的核心理念是通过减少过程变异性来提高产品质量和服务水平。 六西格玛的含义&#xff1a; 统计学概念&am…

一款功能全面的卸载工具,强大,免费,小巧

HiBit Uninstaller是一款功能全面的卸载工具&#xff0c;它不仅可以卸载Windows程序&#xff0c;还提供了诸如注册表清理、垃圾文件清理等多种系统优化功能。该软件以其小巧、强大、免费的特点受到用户的欢迎&#xff0c;尤其适合处理顽固软件和流氓程序的卸载问题。 主要功能…

WPF的MVVM架构:如何通过数据绑定简化UI逻辑

WPF的MVVM架构&#xff1a;如何通过数据绑定简化UI逻辑 目录 MVVM模式概述数据绑定在MVVM中的作用实现MVVM模式的步骤MVVM模式中的常见问题与解决方案实践示例总结 MVVM模式概述 MVVM&#xff08;Model-View-ViewModel&#xff09;是一种设计模式&#xff0c;用于WPF应用程序…

机器学习(五) -- 无监督学习(2) --降维1

系列文章目录及链接 上篇&#xff1a;机器学习&#xff08;五&#xff09; -- 无监督学习&#xff08;1&#xff09; --聚类2 下篇&#xff1a;机器学习&#xff08;五&#xff09; -- 无监督学习&#xff08;2&#xff09; --降维2 前言 tips&#xff1a;标题前有“***”的内…

热门超声波清洗机有哪些?小型超声波清洗机推荐

在繁忙的工作和生活中&#xff0c;许多人常常会因为种种原因忽略日常的小事&#xff0c;比如忘记清洁手表、眼镜、首饰等常用物品。实际上&#xff0c;这些物品表面不仅积累了灰尘和污垢&#xff0c;特别是跟眼部朝夕相处的眼镜&#xff0c;还可能滋生各种致病细菌&#xff0c;…

Vue3-如何自己写一个“返回顶部”功能

功能描述&#xff1a; 在屏幕的右下角固定一个“返回顶部”按钮&#xff0c;只有当用户滚动屏幕一定程度后出现&#xff0c;否则隐藏。 点击按钮&#xff0c;网页平滑的滚动到页面顶部。 环境&#xff1a;Vue3,js&#xff0c;antd 具体思路&#xff1a; 1、给窗口挂载滚动事…

Python 学习中的 API,如何调用API ?

1.1 API的定义 API&#xff0c;全称是Application Programming Interface&#xff08;应用程序编程接口&#xff09;。它是一组定义好的协议和工具&#xff0c;用于在软件应用程序之间进行通信。API可以简化软件开发&#xff0c;使不同的应用程序能够相互协作。它是软件开发中…

阿里云服务器 Ubuntu18.04 安装 mysql8.0并允许外部连接

参考教程&#xff1a; 官网教程 参考教程一 首先彻底删除mysql5.7 dpkg --list|grep mysql #查看 sudo apt-get remove mysql-common #卸载 sudo apt-get autoremove --purge mysql-server-5.7 #版本自己修改 dpkg -l|grep ^rc|awk {print$2}|sudo xargs dpkg -P #清除残留数…

LeetCode Hot100 将有序数组转换为二叉搜索树

给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 平衡 二叉搜索树。 示例 1&#xff1a; 输入&#xff1a;nums [-10,-3,0,5,9] 输出&#xff1a;[0,-3,9,-10,null,5] 解释&#xff1a;[0,-10,5,null,-3,null,9] 也将被视为正确…

电商老司机教您批量下载1688高清主图、详情图、sku及视频信息

图片在电商中至关重要&#xff0c;高质量的商品图片能吸引顾客注意&#xff0c;提升购买欲望。它们是展示商品特性和细节的主要方式&#xff0c;有助于增强消费者信任&#xff0c;减少退换货率。好的图片还能优化搜索排名&#xff0c;提高转化率。简而言之&#xff0c;图片是电…

Luma AI的战略转向:从Nerf到视频生成领域的背后故事

引言 今天我们将深入探讨Luma AI近期引发关注的视频生成模型——Dream Machine。Luma AI从最初的3D重建和生成业务逐步转向视频生成领域的背后&#xff0c;隐藏着什么样的战略考量和技术演进&#xff1f;让我们通过Luma AI首席科学家宋佳铭的最新访谈&#xff0c;揭开这场技术…

【每日一题 | 数据结构】时间复杂度计算

题目 解题方法 对于二重循环求时间复杂度&#xff1a; 写出外层i的变化值写出内层循环语句执行次数&#xff08;看j&#xff09;对次数求和找到频度和n的关系 笔记 视频跳转&#xff1a; 【每日一题 | 数据结构】时间复杂度计算

手写操作系统:二级引导程序

项目简介 在上篇博客&#xff0c;我们完成了主引导扇区的编写&#xff0c;在主引导扇区我们初始化了寄存器&#xff0c;加载了二级引导程序到内存地址 0x8000处&#xff0c;并跳转至0x8000处执行&#xff0c;在本文我们将继续编写二级引导程序。 在二级引导程序将完成以下任务…

Unity UGUI 实战学习笔记(6)

仅作学习&#xff0c;不做任何商业用途 不是源码&#xff0c;不是源码! 是我通过"照虎画猫"写的&#xff0c;可能有些小修改 不提供素材&#xff0c;所以应该不算是盗版资源&#xff0c;侵权删 因为注册和登录面板的逻辑与数据存储方面已经相对完善 服务器面板逻辑…