Skip to main content

Netty源码解析-SizeClasses

Netty版本:4.1.72.Final

Netty的内存对齐类SizeClasses,它为Netty内存池中的内存块提供大小对齐,索引计算等服务方法。 4.1.72.Finaljemalloc4 的实现。jemalloc4 进一步优化了内存碎片的问题。jemalloc4 相较于 jemalloc3 最大的提升是进一步优化内存碎片问题,因为在 jemalloc3 中最多可能会导致 50% 内存碎片,但 jemalloc4 通过划分更细粒度的内存规格在一定程度上改善了这一问题,这也是 SizeClasses 的由来。

Tips: https://github.com/netty/netty/issues/3910 (Netty Issues) 这里说明了jemalloc4的提升

1. Netty内存规格

这里讲的是基于 jemalloc4 实现的内存分配。

Netty内存规格2

jemalloc4 取消了 Tiny 内存的规格。只保留了 smallnormalhuge 三种规格。下面要分析的 SizeClasses 就是记录了 small和normal规格值的一张表。以及一些其他的有用的信息

2. SizeClasses解析

先看一下 SizeClasses 类的说明。

2.1 SizeClasses关键字段说明

  • LOG2_SIZE_CLASS_GROUP: 每次大小加倍时,size类计数的对数。值为:2
  • LOG2_MAX_LOOKUP_SIZE
  • index: 内存块size的索引
  • log2Group:内存块分组
  • log2Delta:增量大小的log2值
  • nDelta:增量乘数
  • isMultiPageSize:表示size是否为page的倍数
  • isSubPage:表示是否为一个subPage类型
  • smallMaxSizeIdx:小规格内存的最小Index
  • sizeClasses:元组表 [index, log2Group, log2Delta, nDelta, isMultiPageSize,isSubPage, log2DeltaLookup]

看一下在Debug模式下 SizeClasses 相关的属性值

sizeClassesdebug相关值

2.2 sizeClasses格式

下面来看一下 sizeClasses 下保存了什么。

源码的介绍中也给了一些说明,但是如果需要一个完整的要怎么办呢? 同样我们可以写写一个简单的Netty项目,然后启动把debug的断点打在类里面如下图方式获取:

nettySizeClasses

表格的数据如下:

indexlog2Grouplog2DeltanDeltaisMultiPageSizeisSubPagelog2DeltaLookupsize
044001416B
144101432B
244201448B
344301464B
464101480B
564201496B
6643014112B
7644014128B
8751015160B
9752015192B
10753015224B
11754015256B
12861016320B
13862016384B
14863016448B
15864016512B
16971017640B
17972017768B
18973017896B
199740171024B
2010810181280B
2110820181536B
2210830181792B
2310840182048B
2411910192560B
2511920193072B
2611930193584B
2711940194096B
28121010105120B
29121020106144B
30121030107168B
31121041108K(PageSize)
321311101010K
331311201012KB
341311301014KB
351311411016KB
361412101020KB
371412211024KB
381412301028KB
391412410032KB
401513110040KB
411513210048KB
421513310056KB
431513410064KB
441614110080KB
451614210096KB
4616143100112KB
4716144100128KB
4817151100160KB
4917152100192KB
5017153100224KB
5117154100256KB
5218161100320KB
5318162100384KB
5418163100448KB
5518164100512KB
5619171100640KB
5719172100768KB
5819173100896KB
59191741001.0MB
60201811001.25MB
61201821001.5MB
62201831001.75MB
63201841002MB
64211911002.5MB
65211921003MB
66211931003.5MB
67211941004MB
68222011005MB
69222021006MB
70222031007MB
71222041008MB
722321110010MB
732321210012MB
742321310014MB
752321410016MB

表格最后面的size如何获取呢?简单的方式还是用debug的方式获取:

image-20220108163159653

使用IDEA的 Add Inline Watch 增加如下的打印

image-20220108163134197

表格说明:

  • 不管是Small和normal的内存规格的内存,分割的粒度更小。
  • isSubPage 列可以看出来, 内存小于等于 28K 表示Subpage

2.3 源码分析

image-20220108170650412

SizeClasses#sizeClasses 方法负责 计算 sizeClasses 表格。SizeClasses 主要负责根据请求的分配的内存大小规范到最接近 sizeClasses 表格中的最接近的大小。

3. 总结

  • SizeClasses 主要是 jemalloc4 的实现,为了更细粒度的管理内存,减少内存碎片的产生
  • jemalloc4 没有做深入的研究,如果有想研究的可以去Github 研究C 的实现
  • jemalloc4 的内存规格减少了Tiny类型,这个也提现在Netty的实现中,在 SizeClass 枚举类中也去掉了 Tiny 类型