博客
关于我
Netty源码—7.ByteBuf原理四
阅读量:789 次
发布时间:2023-02-15

本文共 1770 字,大约阅读时间需要 5 分钟。

Netty内存管理深入解析

Netty作为一个高性能的异步I/O框架,其内存管理机制至关重要。优化内存分配和管理能够显著提升应用性能和稳定性。本文将深入探讨Netty的内存分配机制,包括Page级别和SubPage级别的内存分配流程, PoolChunk的内存组织方式,以及内存回收机制。


1. Netty的内存规格

Netty的内存管理基于Page和SubPage两种规格。Page通常为8KB(8192字节),而SubPage则为16字节。这种规格化设计使得内存管理更加高效,能够根据具体需求灵活分配内存。


2. 缓存数据结构

Netty采用了双层缓存机制:一种是基于Page的内存缓存,另一种是基于SubPage的内存缓存。Page缓存主要用于大块内存的管理,而SubPage缓存则用于小块内存的高效分配。


3. 命中缓存的分配流程

3.1 Page级别内存分配的入口

在实际使用中,Page级别的内存分配通常通过以下代码实现:

PooledByteBufAllocator allocator = PooledByteBufAllocator.DEFAULT;ByteBuf byteBuf = allocator.heapBuffer(8192); // 分配8192B内存byteBuf.release();

3.2 Page级别内存分配的流程

  • 尝试在现有的PoolChunk上分配

    PoolArena中的PoolChunkList通过双向链表连接,每个PoolChunkList代表一种内存使用率的池。PoolArena的allocateNormal()方法会尝试从各个PoolChunkList中获取可用的PoolChunk。

  • 创建一个PoolChunk并进行内存分配

    如果无法从现有PoolChunk中获取,PoolArena会调用newChunk()方法创建一个新的PoolChunk,并调用其allocateRun()方法进行内存分配。

  • 初始化PooledByteBuf对象

    PoolChunk的initBuf()方法会根据分配的内存handle初始化PooledByteBuf对象,设置其内存映射和偏移量。

  • 将新建的PoolChunk添加到PoolChunkList中

    PoolChunk会被添加到PoolArena的qInit PoolChunkList中,等待下次分配使用。


  • 4. SubPage级别内存分配

    4.1 SubPage级别内存分配的入口

    SubPage级别的内存分配通常通过以下代码实现:

    PooledByteBufAllocator allocator = PooledByteBufAllocator.DEFAULT;ByteBuf byteBuf = allocator.directBuffer(16); // 分配16B内存byteBuf.release();

    4.2 SubPage级别内存分配的流程

  • 定位一个SubPage对象

    PoolArena的findSubpagePoolHead()方法会根据内存大小找到对应的SubPage池。

  • 初始化SubPage对象

    如果SubPage池中没有可用的SubPage,会创建一个新的PoolSubpage对象,并初始化其位图和内存映射。

  • 调用SubPage的allocate()方法进行分配

    PoolSubpage的allocate()方法会从位图中寻找未使用的SubPage,并返回对应的handle。


  • 5. ByteBuf的回收

    5.1 池化的内存如何释放

    当ByteBuf被释放时,PooledByteBuf的deallocate()方法会清空相关handle和内存映射,并调用PoolArena的free()方法。

    5.2 将连续内存的区段加到缓存

    PoolArena的freeChunk()方法会将释放的内存区段添加到缓存,并标记为未使用。

    5.3 标记连续内存的区段为未使用

    Page级别的内存管理通过二叉树结构标记内存为未使用,而SubPage级别则通过位图标记。


    6. 将ByteBuf对象添加到对象池

    PooledByteBuf对象在释放后不会立即销毁,而是会被添加到对象池中以供复用。这种机制减少了GC压力,提升了性能。

    转载地址:http://tvcfk.baihongyu.com/

    你可能感兴趣的文章
    MySQL锁与脏读、不可重复读、幻读详解
    查看>>
    mysql锁机制,主从复制
    查看>>
    Mysql锁机制,行锁表锁
    查看>>
    Mysql锁(2):表级锁
    查看>>
    MySQL错误提示mysql Statement violates GTID consistency
    查看>>
    MySQL集群解决方案(4):负载均衡
    查看>>
    mysql面试题学校三表查询_mysql三表查询分组后取每组最大值,mysql面试题。
    查看>>
    Mysql面试题精选
    查看>>
    MySQL面试题集锦
    查看>>
    mysql面试题:为什么MySQL单表不能超过2000W条数据?
    查看>>
    mysql面试题:创建索引时会不会锁表?
    查看>>
    mysql颠覆实战笔记(八)--mysql的自定义异常处理怎么破
    查看>>
    mysql驱动、durid、mybatis之间的关系
    查看>>
    mysql驱动支持中文_mysql 驱动包-Go语言中文社区
    查看>>
    MySQL高可用切换_(5.9)mysql高可用系列——正常主从切换测试
    查看>>
    MySQL高可用解决方案详解
    查看>>
    MYSQL高可用集群MHA架构
    查看>>
    MySQL高级-MySQL并发参数调整
    查看>>
    MySQL高级-MySQL查询缓存优化
    查看>>
    MySQL高级-MySQL锁
    查看>>